-
Notifications
You must be signed in to change notification settings - Fork 5
feat(landing): polish sprint - feedback widget, waitlist modal, theme fixes #232
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
DevanshuNEU
merged 19 commits into
OpenCodeIntel:main
from
DevanshuNEU:feat/polish-sprint-launch
Jan 30, 2026
Merged
Changes from all commits
Commits
Show all changes
19 commits
Select commit
Hold shift + click to select a range
c2c5ef0
feat: add feedback widget and dashboard stats skeleton
DevanshuNEU 4c92600
feat(landing): add waitlist modal for Pro plan signup
DevanshuNEU d095c1c
feat(landing): update hero to showcase GitHub import
DevanshuNEU 27a2857
chore(landing): clean up footer, remove dead links
DevanshuNEU 5329317
chore: rebrand CodeIntel → OpenCodeIntel across entire frontend
DevanshuNEU 8762a52
fix(landing): fix search bar text color in light mode
DevanshuNEU 9158bec
fix(docker): add Discord webhook env var to build args
DevanshuNEU 025b757
feat(landing): Enterprise 'Contact Sales' now uses Discord modal
DevanshuNEU 7dd0405
fix(landing): make search bar theme-aware
DevanshuNEU 4a8d27e
fix(landing): disable search during auto-typing animation
DevanshuNEU f74561f
fix(landing): prevent duplicate searches via Enter key
DevanshuNEU e57acb0
fix(landing): add missing useState import in WaitlistModal
DevanshuNEU e66b611
fix(docs): correct GitHub org name OpenOpenCodeIntel to OpenCodeIntel
DevanshuNEU 5ecf234
fix(backend): add rate_limit decorator to rate_limiter.py
DevanshuNEU 7599dbd
fix(frontend): remove duplicate useState import in WaitlistModal
DevanshuNEU 12f7d20
fix(frontend): add error state handling to FeedbackWidget
DevanshuNEU b993840
fix(frontend): remove duplicate useState import in FeedbackWidget
DevanshuNEU 69b9c5f
fix(backend): add periodic cleanup to rate_limit to prevent memory gr…
DevanshuNEU 90a9c55
fix(backend): require Request for rate limiting, enable proxy headers
DevanshuNEU File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,121 @@ | ||
| """ | ||
| Feedback routes - handles user feedback and waitlist signups | ||
| Posts to Discord webhook server-side to keep webhook URL secret | ||
| """ | ||
| import os | ||
| import httpx | ||
| from datetime import datetime | ||
| from fastapi import APIRouter, HTTPException, Request | ||
| from pydantic import BaseModel, EmailStr | ||
| from typing import Optional | ||
| from services.rate_limiter import rate_limit | ||
|
|
||
| router = APIRouter(prefix="/feedback", tags=["feedback"]) | ||
|
|
||
| DISCORD_WEBHOOK_URL = os.getenv("DISCORD_FEEDBACK_WEBHOOK") | ||
|
|
||
| MOOD_CONFIG = { | ||
| "frustrated": {"emoji": "😠", "color": 0xEF4444, "label": "Frustrated"}, | ||
| "meh": {"emoji": "😐", "color": 0xEAB308, "label": "Meh"}, | ||
| "good": {"emoji": "😊", "color": 0x22C55E, "label": "Good"}, | ||
| "love": {"emoji": "🤩", "color": 0x8B5CF6, "label": "Love it!"}, | ||
| } | ||
|
|
||
|
|
||
| class FeedbackRequest(BaseModel): | ||
| mood: str | ||
| message: Optional[str] = None | ||
| email: Optional[EmailStr] = None | ||
|
|
||
|
|
||
| class WaitlistRequest(BaseModel): | ||
| email: EmailStr | ||
| plan: str # "pro" or "enterprise" | ||
|
|
||
|
|
||
| async def post_to_discord(embed: dict) -> bool: | ||
| """Post an embed to Discord webhook.""" | ||
| if not DISCORD_WEBHOOK_URL: | ||
| return False | ||
|
|
||
| try: | ||
| async with httpx.AsyncClient() as client: | ||
| response = await client.post( | ||
| DISCORD_WEBHOOK_URL, | ||
| json={"embeds": [embed]}, | ||
| timeout=10.0 | ||
| ) | ||
| return response.status_code == 204 | ||
| except Exception: | ||
| return False | ||
|
|
||
|
|
||
| @router.post("") | ||
| @rate_limit(requests_per_minute=5) | ||
| async def submit_feedback(request: Request, body: FeedbackRequest): | ||
| """Submit user feedback - posts to Discord.""" | ||
| if not DISCORD_WEBHOOK_URL: | ||
| raise HTTPException(status_code=503, detail="Feedback service unavailable") | ||
|
|
||
| mood_info = MOOD_CONFIG.get(body.mood, MOOD_CONFIG["good"]) | ||
|
|
||
| embed = { | ||
| "title": "💬 New Feedback", | ||
| "color": mood_info["color"], | ||
| "fields": [ | ||
| {"name": "Mood", "value": f"{mood_info['emoji']} {mood_info['label']}", "inline": True}, | ||
| ], | ||
| "footer": {"text": "OpenCodeIntel Feedback"}, | ||
| "timestamp": datetime.utcnow().isoformat(), | ||
| } | ||
|
|
||
| if body.email: | ||
| embed["fields"].append({"name": "User", "value": body.email, "inline": True}) | ||
|
DevanshuNEU marked this conversation as resolved.
|
||
|
|
||
| if body.message: | ||
| embed["fields"].append({"name": "Message", "value": body.message[:1000], "inline": False}) | ||
|
|
||
| success = await post_to_discord(embed) | ||
| if not success: | ||
| raise HTTPException(status_code=500, detail="Failed to submit feedback") | ||
|
|
||
| return {"success": True} | ||
|
|
||
|
|
||
| @router.post("/waitlist") | ||
| @rate_limit(requests_per_minute=3) | ||
| async def join_waitlist(request: Request, body: WaitlistRequest): | ||
| """Join waitlist for Pro or Enterprise plan.""" | ||
| if not DISCORD_WEBHOOK_URL: | ||
| raise HTTPException(status_code=503, detail="Waitlist service unavailable") | ||
|
|
||
| is_enterprise = body.plan.lower() == "enterprise" | ||
|
|
||
| if is_enterprise: | ||
| embed = { | ||
| "title": "🏢 Enterprise Inquiry", | ||
| "color": 0x8B5CF6, | ||
| "fields": [ | ||
| {"name": "Email", "value": body.email, "inline": True}, | ||
| {"name": "Plan", "value": "Enterprise (Custom)", "inline": True}, | ||
| ], | ||
| "footer": {"text": "OpenCodeIntel Enterprise"}, | ||
| "timestamp": datetime.utcnow().isoformat(), | ||
| } | ||
| else: | ||
| embed = { | ||
| "title": "🚀 New Waitlist Signup", | ||
| "color": 0x3B82F6, | ||
| "fields": [ | ||
| {"name": "Email", "value": body.email, "inline": True}, | ||
| {"name": "Plan Interest", "value": "Pro ($19/month)", "inline": True}, | ||
| ], | ||
| "footer": {"text": "OpenCodeIntel Waitlist"}, | ||
| "timestamp": datetime.utcnow().isoformat(), | ||
| } | ||
|
|
||
| success = await post_to_discord(embed) | ||
| if not success: | ||
| raise HTTPException(status_code=500, detail="Failed to join waitlist") | ||
|
|
||
| return {"success": True} | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.