Skip to content

feat(ui): products nav, calendly, calculator SEO - #2408

Merged
steebchen merged 1 commit into
mainfrom
feat/ui-products-nav-calendly-discord-calculator
May 25, 2026
Merged

steebchen merged 1 commit into
mainfrom
feat/ui-products-nav-calendly-discord-calculator

Conversation

@smakosh

@smakosh smakosh commented May 25, 2026 •

Copy link
Copy Markdown
Member

Summary

Four UI/marketing changes for apps/ui (plus a backend hook in apps/api):

1. Navbar: "Features" → "Products"

  • Renamed the dropdown to Products, limited to AI Gateway, DevPass, Chat Playground, Observability.
  • Moved Integrations and Reliability into Resources. Guardrails was also moved to Resources since it's no longer one of the four products (preserves the existing /features/guardrails link).
  • Removed now-unused icon imports.

2. Enterprise page: Calendly after submit

  • After a successful contact-form submission, the enterprise page now shows an inline Calendly scheduler (https://calendly.com/llmgateway/llmgateway-enterprise) prefilled with the submitter's name/email.
  • Uses Calendly's official inline embed via next/script — no new dependency (avoids React 19 peer-dep friction with react-calendly).

3. Discord notifications

  • Enterprise contact requests now also post to Discord (intended #enterprise channel) via a new DISCORD_ENTERPRISE_NOTIFICATION_URL webhook (notifyEnterpriseContact).
  • Documented 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.
  • Both fall back to DISCORD_NOTIFICATION_URL when unset.

⚠️ Action required (secrets): The actual webhook URLs contain tokens and were not committed (this is a public repo). Set these in deployment secrets:

  • DISCORD_SUPPORT_NOTIFICATION_URL → the #customer-support webhook
  • DISCORD_ENTERPRISE_NOTIFICATION_URL → the #enterprise webhook

4. Token Cost Calculator redesign + SEO (target: #7 → #1)

Design / conversion (token-cost-calculator-client.tsx):

  • Stronger hero with decorative backdrop and a trust strip (200+ models · zero markup · free).
  • Anchoring + loss-aversion framing on results ("At official rates you're overpaying by …") with a CTA at the savings peak.

SEO — the page was a thin interactive widget with little crawlable text. Added:

  • Server-rendered How it works, Understanding LLM token costs explainer, and an FAQ (native <details> so answers stay in the HTML).
  • Three JSON-LD blocks: BreadcrumbList, SoftwareApplication, FAQPage (FAQ schema shares a single source of truth with the rendered FAQ).
  • Per-page canonical, richer title/description/keywords/OG/Twitter metadata, and bumped sitemap priority (0.8 → 0.9, weekly).

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

    • Enterprise contact form now displays an embedded Calendly scheduling widget after successful submission, with name and email pre-filled.
    • Token cost calculator page now includes an FAQ accordion section and step-by-step "How it works" guide.
  • Improvements

    • Token cost calculator messaging updated to emphasize the free offering.
    • Navigation menu: "Features" dropdown renamed to "Products" with refreshed content.
    • Enhanced SEO metadata and structured data for the token cost calculator page.

Review Change Stack

- 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>
@coderabbitai

coderabbitai Bot commented May 25, 2026 •

Copy link
Copy Markdown
Contributor

Walkthrough

This 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.

Changes

Enterprise Contact Discord Notifications

Layer / File(s) Summary
Discord webhook configuration and enterprise notification function
.env.example, apps/api/src/utils/discord.ts
Environment adds DISCORD_ENTERPRISE_NOTIFICATION_URL with fallback to DISCORD_NOTIFICATION_URL. New notifyEnterpriseContact function formats contact details (truncating message to 1000 chars) into a Discord embed and sends via the enterprise webhook URL.
Enterprise contact route notification dispatch
apps/api/src/routes/public-contact.ts
Route imports and calls notifyEnterpriseContact after successful delivery status update, passing contact fields and derived IP address.

Product Marketing and Feature Enhancements

Layer / File(s) Summary
FAQ data structure for token calculator
apps/ui/src/components/token-cost-calculator/faq-data.ts
Introduces CalculatorFaqItem interface and exports CALCULATOR_FAQ constant providing shared FAQ pairs for page rendering and JSON-LD schema generation.
Token calculator page metadata and JSON-LD schemas
apps/ui/src/app/token-cost-calculator/page.tsx
Page-level metadata enhanced with richer title, description, keywords, canonical URL, and OpenGraph/Twitter fields. Defines schema.org JSON-LD objects for breadcrumbs, SoftwareApplication, and FAQPage for SEO and rich snippets.
Token calculator page component and schema injection
apps/ui/src/app/token-cost-calculator/page.tsx
Page component injects three JSON-LD script blocks and integrates new TokenCostCalculatorContent component with existing TokenCostCalculatorClient.
Token calculator informational content component
apps/ui/src/components/token-cost-calculator/token-cost-calculator-content.tsx
New component renders "How it works" ordered steps with icons, explanatory token cost paragraphs, and accordion FAQ from CALCULATOR_FAQ using native <details>/<summary> elements.
Token calculator UI messaging and search visibility
apps/ui/src/components/token-cost-calculator/token-cost-calculator-client.tsx, apps/ui/src/app/sitemap.ts
Header updated with "Free LLM Token Cost Calculator" messaging and decorative background. Savings card revised with updated copy and "Start saving for free" signup CTA. Sitemap priority increased to weekly/0.9.
Enterprise contact booking flow with Calendly widget
apps/ui/src/components/enterprise/calendly-inline.tsx, apps/ui/src/components/enterprise/contact.tsx
New CalendlyInline component loads and initializes Calendly widget via external script. Contact form captures submitted name/email, stores in state, and embeds pre-filled Calendly widget in success state.
Navbar navigation restructure: Features to Products
apps/ui/src/components/landing/navbar.tsx
Navbar dropdown renamed from "Features" to "Products" with reordered entries and external "DevPass" link. Resources expanded to include "Integrations", "Reliability", and "Guardrails". Both mobile and desktop navigation updated to render new product and resource arrays.

🎯 3 (Moderate) | ⏱️ ~20 minutes

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 20.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat(ui): products nav, calendly, calculator SEO' directly reflects the three main UI changes in the PR: navbar products navigation, Calendly integration, and calculator SEO improvements.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/ui-products-nav-calendly-discord-calculator

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (3)
apps/ui/src/components/token-cost-calculator/token-cost-calculator-content.tsx (1)

30-31: ⚡ Quick win

Drop 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 win

Remove 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 win

Remove 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

📥 Commits

Reviewing files that changed from the base of the PR and between ba9b62a and 4838217.

📒 Files selected for processing (11)
  • .env.example
  • apps/api/src/routes/public-contact.ts
  • apps/api/src/utils/discord.ts
  • apps/ui/src/app/sitemap.ts
  • apps/ui/src/app/token-cost-calculator/page.tsx
  • apps/ui/src/components/enterprise/calendly-inline.tsx
  • apps/ui/src/components/enterprise/contact.tsx
  • apps/ui/src/components/landing/navbar.tsx
  • apps/ui/src/components/token-cost-calculator/faq-data.ts
  • apps/ui/src/components/token-cost-calculator/token-cost-calculator-client.tsx
  • apps/ui/src/components/token-cost-calculator/token-cost-calculator-content.tsx

Comment on lines +381 to +388
await notifyEnterpriseContact({
name: validatedData.name,
email: validatedData.email,
country: validatedData.country,
size: validatedData.size,
message: validatedData.message,
ipAddress,
});

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

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.

Suggested change
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.

Comment on lines +7 to +9
const discordEnterpriseWebhookUrl =
process.env.DISCORD_ENTERPRISE_NOTIFICATION_URL ??
process.env.DISCORD_NOTIFICATION_URL;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ 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.

@steebchen
steebchen merged commit 8063d25 into main May 25, 2026
12 checks passed
@steebchen
steebchen deleted the feat/ui-products-nav-calendly-discord-calculator branch May 25, 2026 18:34
serhiizghama pushed a commit to serhiizghama/llmgateway that referenced this pull request May 25, 2026
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 -->

[![Review Change
Stack](https://storage.googleapis.com/coderabbit_public_assets/review-stack-in-coderabbit-ui.svg)](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>
@coderabbitai coderabbitai Bot mentioned this pull request Jul 8, 2026
1 of 6 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants