Uh oh!
There was an error while loading. Please reload this page.
feat(ui): add request a demo modal - #3766
Conversation
The latest updates on your projects. Learn more about Vercel for GitHub. |
TheodoreSpeaks
commented
Mar 25, 2026
@cursor review |
PR SummaryMedium Risk Overview Hardens outbound email handling by adding email-header control character detection and subject sanitization in Improves integrations SEO and rendering by switching metadata/canonicals to Updates docs/data generation: expands HubSpot tool docs (deals/tickets/line items/quotes/appointments/carts/owners/marketing events/lists + pagination fields), tweaks Rippling paging wording, enriches many integration operation descriptions in Written by Cursor Bugbot for commit 769a804. Configure here. |
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
4e89f25 to
aefdc21CompareGreptile SummaryThis PR replaces external Typeform links with a native
Confidence Score: 5/5
Important Files Changed
Sequence DiagramsequenceDiagram
participant User
participant DemoRequestModal
participant API as /api/demo-requests
participant Mailer as mailer.ts
participant Email as Email Provider
User->>DemoRequestModal: Click "Get a demo" / "Book a demo"
DemoRequestModal->>DemoRequestModal: Client-side Zod validation (demoRequestSchema)
alt Validation fails
DemoRequestModal-->>User: Show inline field errors
else Validation passes
DemoRequestModal->>API: POST /api/demo-requests (JSON body)
API->>API: IP rate-limit check (10 tokens/min)
alt Rate limit exceeded
API-->>DemoRequestModal: 429 Too Many Requests
DemoRequestModal-->>User: Show error message
else Within limit
API->>API: Server-side Zod validation + control-char check
API->>Mailer: sendEmail({ to: enterprise@sim.ai, replyTo: companyEmail })
Mailer->>Mailer: prepareEmailHeaders() — validate recipients, sanitize subject
Mailer->>Email: Send transactional email
Email-->>Mailer: Success / Failure
Mailer-->>API: { success: true }
API-->>DemoRequestModal: 201 { success: true }
DemoRequestModal-->>User: Show success screen
end
end
Reviews (3): Last reviewed commit: "fix(upstash): throw on unknown operation..." | Re-trigger Greptile |
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
TheodoreSpeaks
commented
Mar 25, 2026
@greptile review |
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Co-authored-by: Theodore Li <TheodoreSpeaks@users.noreply.github.com>
Co-authored-by: Theodore Li <TheodoreSpeaks@users.noreply.github.com>
Co-authored-by: Theodore Li <TheodoreSpeaks@users.noreply.github.com>
Co-authored-by: Theodore Li <TheodoreSpeaks@users.noreply.github.com>
Co-authored-by: Theodore Li <TheodoreSpeaks@users.noreply.github.com>
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
- Fix endsWith over-matching: basename === 'index.ts'/'types.ts' instead of endsWith(), which was silently skipping valid tool files like list_leave_types.ts, delete_index.ts, etc. - Add extractSwitchCaseToolMapping() to resolve op ID → tool ID mismatches where block switch statements map differently (e.g. HubSpot get_carts → hubspot_list_carts) - Fix double fs.readFileSync in writeIntegrationsJson — reuse existing fileContent variable instead of re-reading the file - Remove 5 dead functions superseded by *FromContent variants - Simplify extractToolsAccessFromContent to use matchAll - fix(upstash): replace template literal tool ID with explicit switch cases
waleedlatif1
commented
Mar 25, 2026
@cursor review |
waleedlatif1
commented
Mar 25, 2026
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
* fix(ui): add request a demo modal * Remove dead code * Remove footer modal * Address greptile comments * Sanatize CRLF characters from emails * extract shared email header safety regex Co-authored-by: Theodore Li <TheodoreSpeaks@users.noreply.github.com> * Use pricing CTA action for demo modal Co-authored-by: Theodore Li <TheodoreSpeaks@users.noreply.github.com> * fix demo request import ordering Co-authored-by: Theodore Li <TheodoreSpeaks@users.noreply.github.com> * merge staging and fix hubspot list formatting Co-authored-by: Theodore Li <TheodoreSpeaks@users.noreply.github.com> * fix(generate-docs): fix tool description extraction and simplify script - Fix endsWith over-matching: basename === 'index.ts'/'types.ts' instead of endsWith(), which was silently skipping valid tool files like list_leave_types.ts, delete_index.ts, etc. - Add extractSwitchCaseToolMapping() to resolve op ID → tool ID mismatches where block switch statements map differently (e.g. HubSpot get_carts → hubspot_list_carts) - Fix double fs.readFileSync in writeIntegrationsJson — reuse existing fileContent variable instead of re-reading the file - Remove 5 dead functions superseded by *FromContent variants - Simplify extractToolsAccessFromContent to use matchAll - fix(upstash): replace template literal tool ID with explicit switch cases * fix(generate-docs): restore extractIconName by aliasing to extractIconNameFromContent * restore * fix(demo-modal): reset form on open to prevent stale success state on reopen * undo hardcoded ff * fix(upstash): throw on unknown operation instead of silently falling back to get --------- Co-authored-by: Theodore Li <teddy@zenobiapay.com> Co-authored-by: Cursor Agent <cursoragent@cursor.com> Co-authored-by: Theodore Li <TheodoreSpeaks@users.noreply.github.com> Co-authored-by: waleed <walif6@gmail.com>
* fix(ui): add request a demo modal * Remove dead code * Remove footer modal * Address greptile comments * Sanatize CRLF characters from emails * extract shared email header safety regex Co-authored-by: Theodore Li <TheodoreSpeaks@users.noreply.github.com> * Use pricing CTA action for demo modal Co-authored-by: Theodore Li <TheodoreSpeaks@users.noreply.github.com> * fix demo request import ordering Co-authored-by: Theodore Li <TheodoreSpeaks@users.noreply.github.com> * merge staging and fix hubspot list formatting Co-authored-by: Theodore Li <TheodoreSpeaks@users.noreply.github.com> * fix(generate-docs): fix tool description extraction and simplify script - Fix endsWith over-matching: basename === 'index.ts'/'types.ts' instead of endsWith(), which was silently skipping valid tool files like list_leave_types.ts, delete_index.ts, etc. - Add extractSwitchCaseToolMapping() to resolve op ID → tool ID mismatches where block switch statements map differently (e.g. HubSpot get_carts → hubspot_list_carts) - Fix double fs.readFileSync in writeIntegrationsJson — reuse existing fileContent variable instead of re-reading the file - Remove 5 dead functions superseded by *FromContent variants - Simplify extractToolsAccessFromContent to use matchAll - fix(upstash): replace template literal tool ID with explicit switch cases * fix(generate-docs): restore extractIconName by aliasing to extractIconNameFromContent * restore * fix(demo-modal): reset form on open to prevent stale success state on reopen * undo hardcoded ff * fix(upstash): throw on unknown operation instead of silently falling back to get --------- Co-authored-by: Theodore Li <teddy@zenobiapay.com> Co-authored-by: Cursor Agent <cursoragent@cursor.com> Co-authored-by: Theodore Li <TheodoreSpeaks@users.noreply.github.com> Co-authored-by: waleed <walif6@gmail.com>

Summary
Migrated over to sim native modal for requesting demos.
Added this modal to pricing and hero pages. I skipped the enterprise section in the top app bar and footer because we're going to have an enterprise page anyways.
demo-request-modalusing EMCN components for use in pricing and hero sections of landing page/demo-requestendpoint to handle sending emails toenterprise@sim.aiType of Change
Testing
Checklist
Screenshots/Videos
hero page screenshot

Success:

Error:

Enterprise "Get a demo" in pricing section

Success:

Error:
