From hypervibe
Internal helper - creates a functional /contact page with a secured form (honeypot anti-spam, rate limiting delegated to the tRPC procedure, HTML injection protection). Detects i18n, email provider (Resend vs Brevo), and shadcn/ui + react-hook-form deps. Invoked by /add-email or any future skill that needs to add a contact UI. Not meant to be called directly by users.
How this skill is triggered — by the user, by Claude, or both
Slash command
/hypervibe:_create-contact-pageThis skill is limited to the following tools:
The summary Claude sees in its skill listing — used to decide when to auto-load this skill
- Detect the user's language from their messages and ALWAYS reply in that language (default: English). This applies to every user-facing message: questions, progress, confirmations, summaries, errors.
Creates a functional /contact page with a secured form (invisible honeypot anti-spam, server-side rate limiting, HTML/Brevo escaping on every user field). Invoked by /add-email after the user has accepted the offer to create it.
Expected prerequisites (normally guaranteed by the calling skill):
contact.send exists (created by add-email)mail.ts utility exports sendMail + the escape function (escapeHtml for Resend, escapeForBrevo for Brevo)/bootstrap)Invoke _detect-project-root to retrieve PROJECT_NAME, WEB_DIR, IS_MONOREPO, IS_NEXTJS.
Invoke _check-deps email i18n:
result=$(node "${CLAUDE_SKILL_DIR}/../../scripts/check-deps.mjs" email i18n)
email_provider=$(echo "$result" | node -e "console.log(JSON.parse(require('fs').readFileSync(0,'utf8')).email.provider || 'none')")
i18n_ok=$(echo "$result" | node -e "console.log(JSON.parse(require('fs').readFileSync(0,'utf8')).i18n.ok)")
If email_provider === "none" -> abort: the contact page depends on a functional email backend. Inform the calling skill and create nothing.
Otherwise (resend or brevo) -> continue. The React client page is identical in both cases (the HTML/Brevo escaping happens server-side in contact.send, not in the page). No need to distinguish.
Also retrieve the current sender email from the local env (useful for Step 2):
SENDER_EMAIL_VAR=$(case "$email_provider" in resend) echo "RESEND_FROM_EMAIL";; brevo) echo "BREVO_SENDER_EMAIL";; esac)
CURRENT_SENDER=$(grep -E "^${SENDER_EMAIL_VAR}=" .env 2>/dev/null | head -1 | sed -E "s/^${SENDER_EMAIL_VAR}=//" | tr -d '"' | tr -d "'")
The goal: a default that actually works for receiving the emails. The sender is not always a good choice (e.g. [email protected] is NOT an inbox - emails sent there disappear silently).
The Resend API does not cleanly expose the account email -> we ask the user directly for the receiving address (better UX: explicit rather than guessed). For Brevo, the CURRENT_SENDER (verified address) remains a reasonable default to propose.
Proposed default:
$CURRENT_SENDER if it is defined and is not [email protected].$CURRENT_SENDER (verified address, real inbox).If the current sender is [email protected], warn the user that receiving will not work until they provide a real address.
Ask the user (plain language, no jargon):
📬 Which address do you want to receive the form messages at?
When someone fills out your contact form, their message is sent to you by email. Tell me where you want to receive them:
- By default: at
<DEFAULT_RECIPIENT>(<explanation: "your Resend email" if owner, otherwise "the sending address you just configured">)- Another address: give me another address (e.g. your personal Gmail
[email protected])Tell me "leave the default" or type the address you want.
Whatever the choice, always push CONTACT_RECIPIENT_EMAIL via _push-env-vars (we do not rely on the tRPC procedure fallback for the nominal case - the fallback remains only a safety belt):
If "leave the default" -> RECIPIENT = $DEFAULT_RECIPIENT.
If the user gives a different address -> RECIPIENT = <provided address>. Quickly validate that it looks like an email (contains @ and at least one . after it). If invalid, ask again.
Then in both cases:
node "${CLAUDE_SKILL_DIR}/../../scripts/push-env-vars.mjs" "CONTACT_RECIPIENT_EMAIL=$RECIPIENT"
The helper updates the local .env AND Vercel (production/preview/development) in a single idempotent operation. The tRPC procedure contact.send reads process.env.CONTACT_RECIPIENT_EMAIL.
⚠️ Brevo note: if the provider is Brevo and the user gives a custom address, remind them that Brevo does not require formal validation of the recipient (unlike the sender, which must be verified). No blocking, but if the address is wrong, the email will disappear silently (Brevo 201-then-async-fail).
Check in <WEB_DIR>/package.json:
grep -qE '"(react-hook-form|@hookform/resolvers|zod)"' "<WEB_DIR>/package.json"
If any of the three is missing, install:
cd <WEB_DIR> && pnpm add react-hook-form @hookform/resolvers zod
The page needs: card, input, textarea, button, label, alert. Check that each is present in <WEB_DIR>/src/components/ui/:
for c in card input textarea button label alert; do
[ -f "<WEB_DIR>/src/components/ui/$c.tsx" ] || MISSING="$MISSING $c"
done
If MISSING is non-empty, install:
cd <WEB_DIR> && pnpm dlx shadcn@latest add$MISSING
The contact page follows the plugin's standard i18n-aware feature pattern. All the files (plain.tsx, i18n.tsx, messages-fr.json, messages-en.json) are in templates/contact-page/ at the plugin root.
PLUGIN_ROOT="${CLAUDE_SKILL_DIR}/../.."
if [ "$i18n_ok" = "true" ]; then
VARIANT="i18n"
DEST="<WEB_DIR>/src/app/[locale]/contact/page.tsx"
else
VARIANT="plain"
DEST="<WEB_DIR>/src/app/contact/page.tsx"
fi
mkdir -p "$(dirname "$DEST")"
cp "$PLUGIN_ROOT/templates/contact-page/$VARIANT.tsx" "$DEST"
if [ "$i18n_ok" = "true" ]; then
node "$PLUGIN_ROOT/scripts/_i18n-merge-messages.mjs" --web-dir "<WEB_DIR>" --feature contact-page
fi
The helper merges the contact.* keys into every messages/<locale>.json in the project. EN fallback for the locales the template does not ship (the helper warns about those locales). If other languages are present (e.g. es.json, de.json), warn the user that the translations must be completed manually.
Do not display a clean summary (the calling skill produces its own final summary). Just confirm the path of the created page:
CONTACT_PAGE_CREATED: <DEST>
The calling skill will integrate this info into its user-facing summary.
npx claudepluginhub flavien-ia/hypervibe-harness --plugin hypervibeAdd transactional email support (Resend or Brevo) to an existing T3 project. The skill auto-detects which provider to use based on env vars - no question asked when the choice is unambiguous. Can be called by /bootstrap or standalone.
Guides users in creating, optimizing, or auditing contact pages and forms, covering form design, field labels, CTAs, trust signals, and accessibility.
Generates validated, accessible form pages for contact forms, registrations, surveys, sign-ups, and multi-step wizards. Detects project tech stack to produce matching code with real-time validation, error handling, and a11y.