Add BFF route example for sending contact form inquiries as mail - #1656
Open
VPS-julia wants to merge 9 commits into
Open
Add BFF route example for sending contact form inquiries as mail#1656VPS-julia wants to merge 9 commits into
VPS-julia wants to merge 9 commits into
Conversation
Contact form inquiries are of no interest to the CMS, so they are handled in the BFF instead of the API: the new route handler validates the submitted values and sends them as a mail via nodemailer. The corresponding form is not part of the starter. Mailpit is added to the docker-compose services so mails sent in development are caught locally and can be viewed at http://localhost:8025. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014QS28L7gMaUqTqRSJmFejN
Read the required environment variables directly where they are used. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014QS28L7gMaUqTqRSJmFejN
…kage Parse the port with parseInt and a string default, as in server.ts and cache-handler.ts, and validate the host where it is used. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014QS28L7gMaUqTqRSJmFejN
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014QS28L7gMaUqTqRSJmFejN
The starter is boilerplate, a project fills in the sender and recipient addresses itself. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014QS28L7gMaUqTqRSJmFejN
The site name was only used to prefix the mail subject, which the form already provides. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014QS28L7gMaUqTqRSJmFejN
Send the mail inline in the route instead of in a separate util, and adopt the validation and response shape of the example. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014QS28L7gMaUqTqRSJmFejN
The starter doesn't contain a form, so it can't know which fields a project needs. Validate and send only the address to reply to and the message. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014QS28L7gMaUqTqRSJmFejN
…oute-11gyec Resolved the conflicts in site/package.json by taking the dependency updates from main and keeping nodemailer, zod and @types/nodemailer. site/package-lock.json was regenerated with npm instead of merged by hand. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014QS28L7gMaUqTqRSJmFejN
VPS-julia
marked this pull request as ready for review
September 2, 2026 14:52
VPS-Obi
reviewed
Sep 3, 2026
VPS-Obi
left a comment
Contributor
There was a problem hiding this comment.
I don't think this should be in the Starter as there's no contact form. Instead, the contact form's data should be send as email in the Demo's BFF (it currently only performs validation): https://github.com/vivid-planet/dextinity/blob/main/demo/site/src/app/%5Bvisibility%5D/%5Bdomain%5D/%5Blanguage%5D/api/contact-form/route.tsx#L49
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
Description
Adds an example for a BFF route to the starter: it receives the values of a contact form, validates them and sends them as a mail. The mail is sent in the BFF and not in the API, because the inquiries are of no interest to the CMS.
The route follows the example implementation in vivid-planet/dextinity#4963 and adds the mail sending in its
tryblock. Since the starter contains no form, the validation is reduced to the fields any contact form needs: the address to reply to and the message. A project extends the schema with its own fields.The corresponding form is not part of this PR — the starter only provides the route as an example.
Changes
site/src/app/[visibility]/[domain]/api/contact-form/route.ts(new):POSThandler. Validates the request body with zod, answers with 400 and the validation error on invalid input, and otherwise sends the message as a mail with nodemailer, with the submitted address inReply-To. Errors are logged and answered with 500. The[visibility]and[domain]segments are added by the domain rewrite middleware, so a form would submit to/api/contact-form.docker-compose.ymland.env: add Mailpit, which catches all mails sent in development and shows them at http://localhost:8025, together with theMAIL_*andCONTACT_FORM_TO_EMAILvariables.MAIL_HOSTandMAIL_PORTpoint at Mailpit; the sender and recipient addresses are left empty, because the starter is boilerplate and a project fills them in itself. The deployment configurations are unchanged — a project supplies its own SMTP credentials there.site/package.json: addnodemailer,zodand@types/nodemailer.AGENTS.md: document the BFF route pattern and the Mailpit service.Testing
Sending was tested against Mailpit: the mail arrives with the expected
From,To,Reply-Toand subject.https://vivid-planet.atlassian.net/browse/COM-2702
https://claude.ai/code/session_014QS28L7gMaUqTqRSJmFejN