Repository navigation
feat(ui): products nav, calendly, calculator SEO - #2408
Conversation
- Rename "Features" nav to "Products" with only AI Gateway, DevPass, Chat Playground, and Observability; move Integrations, Reliability, and Guardrails into Resources. - Enterprise contact form now shows a Calendly scheduler (prefilled with name/email) after a successful submission, via the official inline embed (no new dependency). - Post enterprise contact requests to Discord through a new DISCORD_ENTERPRISE_NOTIFICATION_URL webhook; document the existing DISCORD_SUPPORT_NOTIFICATION_URL (chat support) in .env.example. - Redesign the token cost calculator: stronger hero with trust strip, loss-aversion savings framing, plus server-rendered how-it-works, explainer, and FAQ content. Add BreadcrumbList, SoftwareApplication, and FAQPage JSON-LD, per-page canonical, richer metadata, and bump sitemap priority for SEO. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
WalkthroughThis PR adds Discord notifications for enterprise contact submissions and substantially enhances the token cost calculator page with richer metadata, educational content, and booking integration. The backend wires notification dispatch into the contact route, while the frontend refactors navbar navigation and expands calculator visibility and user journey. ChangesEnterprise Contact Discord Notifications
Product Marketing and Feature Enhancements
🎯 3 (Moderate) | ⏱️ ~20 minutes 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (3)
apps/ui/src/components/token-cost-calculator/token-cost-calculator-content.tsx (1)
30-31: ⚡ Quick winDrop section-label JSX comments to align with project style.
These comments are non-essential and should be removed in TSX files per repo convention.
As per coding guidelines: "
**/*.{ts,tsx}: No unnecessary code comments".Also applies to: 76-77, 131-132
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/ui/src/components/token-cost-calculator/token-cost-calculator-content.tsx` around lines 30 - 31, Remove the non-essential JSX comments inside the TokenCostCalculatorContent component (the "How it works" and the other two inline section-label comments) so the TSX matches project style; locate the comments near the section elements in token-cost-calculator-content.tsx (inside the TokenCostCalculatorContent component) and delete those {/* ... */} comment nodes (the ones around "How it works" and the ones at the other two noted locations) leaving the section elements and their children intact.apps/ui/src/components/token-cost-calculator/faq-data.ts (1)
6-10: ⚡ Quick winRemove the non-essential block comment.
This descriptive comment can be dropped to match the repo rule for TS/TSX files.
As per coding guidelines: "
**/*.{ts,tsx}: No unnecessary code comments".🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/ui/src/components/token-cost-calculator/faq-data.ts` around lines 6 - 10, Remove the non-essential top-of-file block comment in faq-data.ts (the multi-line /** ... */ header describing the FAQ source); delete those comment lines so the file contains only the actual exported data/constants (e.g., whatever FAQ data identifiers are defined below) to comply with the repo rule banning unnecessary comments in .ts/.tsx files.apps/ui/src/components/token-cost-calculator/token-cost-calculator-client.tsx (1)
300-300: ⚡ Quick winRemove this decorative JSX comment.
The label is non-functional and should be omitted to match TS/TSX comment policy.
As per coding guidelines: "
**/*.{ts,tsx}: No unnecessary code comments".🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/ui/src/components/token-cost-calculator/token-cost-calculator-client.tsx` at line 300, Remove the non-functional JSX comment {/* Decorative backdrop */} from the TokenCostCalculatorClient component (look for the token-cost-calculator-client.tsx file and the Decorative backdrop JSX comment inside the component render/return); delete this unnecessary comment to comply with the TS/TSX comment policy and then run typecheck/format to ensure no stray whitespace or formatting issues remain.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@apps/api/src/routes/public-contact.ts`:
- Around line 381-388: The current code awaits notifyEnterpriseContact(...)
which blocks the HTTP response on the external Discord webhook; change the flow
to send the core success response first, then dispatch notifyEnterpriseContact
asynchronously without awaiting it (e.g., fire-and-forget or schedule in
background) so request handling isn't delayed; locate the call to
notifyEnterpriseContact in the public-contact handler and move/modify it so the
webhook is invoked after the handler confirms core delivery (or wrapped in a
non-blocking promise) while still ensuring any errors from
notifyEnterpriseContact are logged but do not affect the HTTP response.
In `@apps/api/src/utils/discord.ts`:
- Around line 7-9: Remove the top-level cached variable
discordEnterpriseWebhookUrl and instead resolve
process.env.DISCORD_ENTERPRISE_NOTIFICATION_URL (falling back to
process.env.DISCORD_NOTIFICATION_URL) at call time inside the sender function
(e.g., in the function that posts webhook messages or a new getDiscordWebhookUrl
helper called from that sender); update any references to use this runtime
lookup so no module-scope process.env read is performed.
---
Nitpick comments:
In `@apps/ui/src/components/token-cost-calculator/faq-data.ts`:
- Around line 6-10: Remove the non-essential top-of-file block comment in
faq-data.ts (the multi-line /** ... */ header describing the FAQ source); delete
those comment lines so the file contains only the actual exported data/constants
(e.g., whatever FAQ data identifiers are defined below) to comply with the repo
rule banning unnecessary comments in .ts/.tsx files.
In
`@apps/ui/src/components/token-cost-calculator/token-cost-calculator-client.tsx`:
- Line 300: Remove the non-functional JSX comment {/* Decorative backdrop */}
from the TokenCostCalculatorClient component (look for the
token-cost-calculator-client.tsx file and the Decorative backdrop JSX comment
inside the component render/return); delete this unnecessary comment to comply
with the TS/TSX comment policy and then run typecheck/format to ensure no stray
whitespace or formatting issues remain.
In
`@apps/ui/src/components/token-cost-calculator/token-cost-calculator-content.tsx`:
- Around line 30-31: Remove the non-essential JSX comments inside the
TokenCostCalculatorContent component (the "How it works" and the other two
inline section-label comments) so the TSX matches project style; locate the
comments near the section elements in token-cost-calculator-content.tsx (inside
the TokenCostCalculatorContent component) and delete those {/* ... */} comment
nodes (the ones around "How it works" and the ones at the other two noted
locations) leaving the section elements and their children intact.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: 282aa3a2-4f61-47a1-901d-d93de4a403ba
📒 Files selected for processing (11)
.env.exampleapps/api/src/routes/public-contact.tsapps/api/src/utils/discord.tsapps/ui/src/app/sitemap.tsapps/ui/src/app/token-cost-calculator/page.tsxapps/ui/src/components/enterprise/calendly-inline.tsxapps/ui/src/components/enterprise/contact.tsxapps/ui/src/components/landing/navbar.tsxapps/ui/src/components/token-cost-calculator/faq-data.tsapps/ui/src/components/token-cost-calculator/token-cost-calculator-client.tsxapps/ui/src/components/token-cost-calculator/token-cost-calculator-content.tsx
| await notifyEnterpriseContact({ | ||
| name: validatedData.name, | ||
| email: validatedData.email, | ||
| country: validatedData.country, | ||
| size: validatedData.size, | ||
| message: validatedData.message, | ||
| ipAddress, | ||
| }); |
There was a problem hiding this comment.
Do not block the response on Discord webhook delivery.
This awaits an external webhook on the request path, so slow/unavailable Discord can delay successful form submissions. Dispatch it asynchronously after core delivery succeeds.
Suggested change
- await notifyEnterpriseContact({
+ void notifyEnterpriseContact({
name: validatedData.name,
email: validatedData.email,
country: validatedData.country,
size: validatedData.size,
message: validatedData.message,
ipAddress,
});📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| await notifyEnterpriseContact({ | |
| name: validatedData.name, | |
| email: validatedData.email, | |
| country: validatedData.country, | |
| size: validatedData.size, | |
| message: validatedData.message, | |
| ipAddress, | |
| }); | |
| void notifyEnterpriseContact({ | |
| name: validatedData.name, | |
| email: validatedData.email, | |
| country: validatedData.country, | |
| size: validatedData.size, | |
| message: validatedData.message, | |
| ipAddress, | |
| }); |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@apps/api/src/routes/public-contact.ts` around lines 381 - 388, The current
code awaits notifyEnterpriseContact(...) which blocks the HTTP response on the
external Discord webhook; change the flow to send the core success response
first, then dispatch notifyEnterpriseContact asynchronously without awaiting it
(e.g., fire-and-forget or schedule in background) so request handling isn't
delayed; locate the call to notifyEnterpriseContact in the public-contact
handler and move/modify it so the webhook is invoked after the handler confirms
core delivery (or wrapped in a non-blocking promise) while still ensuring any
errors from notifyEnterpriseContact are logged but do not affect the HTTP
response.
| const discordEnterpriseWebhookUrl = | ||
| process.env.DISCORD_ENTERPRISE_NOTIFICATION_URL ?? | ||
| process.env.DISCORD_NOTIFICATION_URL; |
There was a problem hiding this comment.
🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win
Avoid adding top-level cached env reads for webhook config.
This introduces another cached process.env read at module scope. Please resolve the enterprise webhook URL at call time (or inside the sender) instead.
Suggested change
-const discordEnterpriseWebhookUrl =
- process.env.DISCORD_ENTERPRISE_NOTIFICATION_URL ??
- process.env.DISCORD_NOTIFICATION_URL;
+function getDiscordEnterpriseWebhookUrl(): string | undefined {
+ return (
+ process.env.DISCORD_ENTERPRISE_NOTIFICATION_URL ??
+ process.env.DISCORD_NOTIFICATION_URL
+ );
+}
...
- discordEnterpriseWebhookUrl,
+ getDiscordEnterpriseWebhookUrl(),As per coding guidelines "Do not add explicit caching or memoization around process.env reads or parsed env-var values unless there is a measured hot-path need".
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@apps/api/src/utils/discord.ts` around lines 7 - 9, Remove the top-level
cached variable discordEnterpriseWebhookUrl and instead resolve
process.env.DISCORD_ENTERPRISE_NOTIFICATION_URL (falling back to
process.env.DISCORD_NOTIFICATION_URL) at call time inside the sender function
(e.g., in the function that posts webhook messages or a new getDiscordWebhookUrl
helper called from that sender); update any references to use this runtime
lookup so no module-scope process.env read is performed.
Follow-up to theopenco#2408 addressing two review findings. Both verified still valid against current `main`. ### 1. Don't block the HTTP response on the Discord webhook `apps/api/src/routes/public-contact.ts` awaited `notifyEnterpriseContact(...)` before returning, so the enterprise contact request waited on an external Discord call before responding. Now it's fire-and-forget (`void … .catch(log)`) dispatched after core delivery is confirmed, so request latency no longer depends on Discord. `notifyEnterpriseContact` already logs its own failures; the added `.catch` guards against an unhandled rejection. ### 2. Resolve the enterprise webhook env at call time `apps/api/src/utils/discord.ts` cached `DISCORD_ENTERPRISE_NOTIFICATION_URL` in a module-scope const. Removed it and resolve `process.env.DISCORD_ENTERPRISE_NOTIFICATION_URL ?? process.env.DISCORD_NOTIFICATION_URL` inside `notifyEnterpriseContact` instead — no module-load env read. **Note:** left the pre-existing `discordSupportWebhookUrl` / `discordWebhookUrl` module-scope reads untouched to keep this change minimal and scoped to the findings. ## Testing - `pnpm turbo run build --filter=api` ✅ (lint-staged eslint/prettier ran clean on commit) 🤖 Generated with [Claude Code](https://claude.com/claude-code) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Improved error handling for enterprise contact notifications to prevent form submission response delays. * **Performance** * Optimized Discord notification delivery for enterprise contacts to process asynchronously, ensuring faster form submission responses. <!-- review_stack_entry_start --> [](https://app.coderabbit.ai/change-stack/theopenco/llmgateway/pull/2409?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack) <!-- review_stack_entry_end --> <!-- end of auto-generated comment: release notes by coderabbit.ai --> Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Summary
Four UI/marketing changes for
apps/ui(plus a backend hook inapps/api):1. Navbar: "Features" → "Products"
/features/guardrailslink).2. Enterprise page: Calendly after submit
https://calendly.com/llmgateway/llmgateway-enterprise) prefilled with the submitter's name/email.next/script— no new dependency (avoids React 19 peer-dep friction withreact-calendly).3. Discord notifications
DISCORD_ENTERPRISE_NOTIFICATION_URLwebhook (notifyEnterpriseContact).DISCORD_SUPPORT_NOTIFICATION_URL(chat support escalations, intended #customer-support channel) in.env.example. The chat-support channel switch is purely a config change — the code already reads this var; no code change was required.DISCORD_NOTIFICATION_URLwhen unset.4. Token Cost Calculator redesign + SEO (target: #7 → #1)
Design / conversion (
token-cost-calculator-client.tsx):SEO — the page was a thin interactive widget with little crawlable text. Added:
<details>so answers stay in the HTML).Testing
pnpm format✅ /pnpm lint✅pnpm turbo run build --filter=api --filter=ui✅ (13/13 tasks)🤖 Generated with Claude Code
Summary by CodeRabbit
New Features
Improvements