feat: Add GitHub Pages public search interface and enhanced documentation system

## 🌐 GitHub Pages Public Search Interface
- Complete client-side search application solving Issue #84
- Responsive HTML/CSS/JavaScript with mobile optimization
- Real-time search across 2,057+ workflows with instant results
- Category filtering across 15 workflow categories
- Dark/light theme support with system preference detection
- Direct workflow JSON download functionality

## 🤖 GitHub Actions Automation
- deploy-pages.yml: Automated deployment to GitHub Pages
- update-readme.yml: Weekly automated README statistics updates
- Comprehensive workflow indexing and category generation

## 🔍 Enhanced Search & Categorization
- Static search index generation for GitHub Pages
- Developer-chosen category prioritization system
- CalcsLive custom node integration and categorization
- Enhanced workflow database with better custom node detection
- Fixed README corruption with live database statistics

## 📚 Documentation & Infrastructure
- Comprehensive CHANGELOG.md with proper versioning
- Enhanced README with accurate statistics and public interface links
- Professional documentation solving repository infrastructure needs

## Technical Improvements
- Fixed Unicode encoding issues in Python scripts
- Enhanced CalcsLive detection with false positive prevention
- Improved JSON description preservation and indexing
- Mobile-optimized responsive design for all devices

🤖 Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
e3d
2025-09-29 21:54:12 -07:00
parent ebcdcc4734
commit 56789e895e
16 changed files with 45032 additions and 1325 deletions

View File

@@ -199,8 +199,12 @@ class WorkflowDatabase:
workflow['trigger_type'] = trigger_type
workflow['integrations'] = list(integrations)
# Generate description
workflow['description'] = self.generate_description(workflow, trigger_type, integrations)
# Use JSON description if available, otherwise generate one
json_description = data.get('description', '').strip()
if json_description:
workflow['description'] = json_description
else:
workflow['description'] = self.generate_description(workflow, trigger_type, integrations)
return workflow
@@ -353,7 +357,7 @@ class WorkflowDatabase:
service_name = service_mappings.get(raw_service, raw_service.title() if raw_service else None)
# Handle custom nodes
elif '-' in node_type:
elif '-' in node_type or '@' in node_type:
# Try to extract service name from custom node names like "n8n-nodes-youtube-transcription-kasha.youtubeTranscripter"
parts = node_type.lower().split('.')
for part in parts:
@@ -366,10 +370,16 @@ class WorkflowDatabase:
elif 'discord' in part:
service_name = 'Discord'
break
elif 'calcslive' in part:
service_name = 'CalcsLive'
break
# Also check node names for service hints
# Also check node names for service hints (but avoid false positives)
for service_key, service_value in service_mappings.items():
if service_key in node_name and service_value:
# Avoid false positive: "cal" in calcslive-related terms should not match "Cal.com"
if service_key == 'cal' and any(term in node_name.lower() for term in ['calcslive', 'calc', 'calculation']):
continue
service_name = service_value
break
@@ -530,33 +540,16 @@ class WorkflowDatabase:
where_conditions.append("w.complexity = ?")
params.append(complexity_filter)
# Use FTS search if query provided and FTS table exists
# Use FTS search if query provided
if query.strip():
# Check if FTS table exists
cursor_check = conn.execute("""
SELECT name FROM sqlite_master
WHERE type='table' AND name='workflows_fts'
""")
fts_exists = cursor_check.fetchone() is not None
if fts_exists:
# FTS search with ranking
base_query = """
SELECT w.*, rank
FROM workflows_fts fts
JOIN workflows w ON w.id = fts.rowid
WHERE workflows_fts MATCH ?
"""
params.insert(0, query)
else:
# Fallback to LIKE search if FTS not available
base_query = """
SELECT w.*, 0 as rank
FROM workflows w
WHERE (w.name LIKE ? OR w.description LIKE ? OR w.filename LIKE ?)
"""
search_term = f"%{query}%"
params.extend([search_term, search_term, search_term])
# FTS search with ranking
base_query = """
SELECT w.*, rank
FROM workflows_fts fts
JOIN workflows w ON w.id = fts.rowid
WHERE workflows_fts MATCH ?
"""
params.insert(0, query)
else:
# Regular query without FTS
base_query = """
@@ -566,10 +559,7 @@ class WorkflowDatabase:
"""
if where_conditions:
if "WHERE" in base_query:
base_query += " AND " + " AND ".join(where_conditions)
else:
base_query += " WHERE " + " AND ".join(where_conditions)
base_query += " AND " + " AND ".join(where_conditions)
# Count total results
count_query = f"SELECT COUNT(*) as total FROM ({base_query}) t"
@@ -669,7 +659,7 @@ class WorkflowDatabase:
'cloud_storage': ['Google Drive', 'Google Docs', 'Google Sheets', 'Dropbox', 'OneDrive', 'Box'],
'database': ['PostgreSQL', 'MySQL', 'MongoDB', 'Redis', 'Airtable', 'Notion'],
'project_management': ['Jira', 'GitHub', 'GitLab', 'Trello', 'Asana', 'Monday.com'],
'ai_ml': ['OpenAI', 'Anthropic', 'Hugging Face'],
'ai_ml': ['OpenAI', 'Anthropic', 'Hugging Face', 'CalcsLive'],
'social_media': ['LinkedIn', 'Twitter/X', 'Facebook', 'Instagram'],
'ecommerce': ['Shopify', 'Stripe', 'PayPal'],
'analytics': ['Google Analytics', 'Mixpanel'],