We work directly with every client — no account managers, no handoffs. When you contact Tech Velocity, you're talking to the veteran who runs it.

Response Commitments
Initial response within 24 hours
Project scoping call within 48 hours
Written proposal within 5 business days
Retainer clients: under 4-hour response
Send a Message

Fill out the form and we'll be in touch. All fields marked * are required.

Contact form

Valid name required (2–80 letters).
Valid email address required.
Please select a service.
Message required (10–3000 characters). 0 / 3000
Developer Setup

Activating the Contact Form

The form is fully built and OWASP-hardened. Once your S3 bucket and Zoho account are ready, follow these steps to make it live. The endpoint URL in js/tv-contact.js is the only thing you need to update.

1
Set Up Zoho Mail (Free)
Go to zoho.com/mailSign up for Free (Zoho Mail Free Plan).

Add your domain (e.g. techvelocity.dev) → Verify via DNS TXT record in Route 53 or your registrar.

Create the mailbox [email protected].

Then go to Settings → Mail Accounts → SMTP and note:
Host: smtp.zoho.com · Port: 587 · TLS: STARTTLS
Username: [email protected]
Password: generate an App Password under Security settings (required if 2FA enabled).
2
Create AWS Lambda Function
In AWS Console → Lambda → Create Function.
Runtime: Node.js 20.x · Name: tv-contact-mailer

Paste the Lambda code shown below (or deploy via aws-lambda.zip in this repo).

Add environment variables:
ZOHO_USER[email protected]
ZOHO_PASS → your Zoho App Password
TO_EMAIL[email protected]
ALLOWED_ORIGINhttps://techvelocity.dev

Never hard-code credentials. Use AWS Secrets Manager or Parameter Store for production.
3
Create API Gateway Endpoint
AWS Console → API Gateway → Create API → HTTP API.

Add integration → Lambda → select tv-contact-mailer.
Add route: POST /contact

Under CORS, set:
Allow-Origin: https://techvelocity.dev
Allow-Methods: POST, OPTIONS
Allow-Headers: Content-Type

Deploy the API → copy the Invoke URL.
It looks like: https://abc123.execute-api.us-east-1.amazonaws.com
4
Update the Site & Go Live
Open js/tv-contact.js and replace the placeholder:
API_ENDPOINT = 'https://YOUR-API-ID.execute-api...'
→ paste your API Gateway Invoke URL + /contact

Also update the CSP header in contact.html line 10 — replace YOUR-API-ID with your real API Gateway subdomain.

Upload all files to S3 → invalidate the CloudFront cache → test the form.
Check your Zoho inbox. Done. Mission complete. ✓
Lambda Function — tv-contact-mailer / index.mjs Node.js 20.x · nodemailer via Lambda Layer
// ── tv-contact-mailer/index.mjs ─────────────────────────────────────────
// Deploy as AWS Lambda (Node.js 20.x).
// Requires nodemailer — add as Lambda Layer or bundle with npm.
// Environment variables (set in Lambda Console → Configuration → Env Vars):
//   ZOHO_USER      → [email protected]
//   ZOHO_PASS      → Zoho App Password (from Zoho Security settings)
//   TO_EMAIL       → [email protected]
//   ALLOWED_ORIGIN → https://techvelocity.dev

import nodemailer from 'nodemailer';

const ALLOWED_ORIGIN = process.env.ALLOWED_ORIGIN || '';
const MAX_FIELD_LEN  = { name: 80, email: 254, company: 120, service: 40, budget: 20, message: 3000 };

/* ── Sanitize: strip HTML, trim, enforce max length ── */
function sanitize(str, max) {
  return String(str || '')
    .replace(//[<>&"']/g, '')  // strip common injection chars
    .trim()
    .slice(0, max || 3000);
}

/* ── Validate email format ── */
function validEmail(e) {
  return /^[^\s@]+@[^\s@]+\.[^\s@]{2,}$/.test(e) && e.length <= 254;
}

export const handler = async (event) => {
  const cors = {
    'Access-Control-Allow-Origin':  ALLOWED_ORIGIN,
    'Access-Control-Allow-Headers': 'Content-Type',
    'Access-Control-Allow-Methods': 'POST, OPTIONS',
  };

  /* Preflight */
  if (event.requestContext?.http?.method === 'OPTIONS') {
    return { statusCode: 204, headers: cors, body: '' };
  }

  let body;
  try { body = JSON.parse(event.body || '{}'); }
  catch { return { statusCode: 400, headers: cors, body: JSON.stringify({ ok: false }) }; }

  /* OWASP A07 — Honeypot check */
  if (body.website && body.website.length > 0) {
    return { statusCode: 200, headers: cors, body: JSON.stringify({ ok: true }) }; // silent reject
  }

  /* OWASP A03 — Re-sanitize every field server-side */
  const name    = sanitize(body.name,    MAX_FIELD_LEN.name);
  const email   = sanitize(body.email,   MAX_FIELD_LEN.email);
  const company = sanitize(body.company, MAX_FIELD_LEN.company);
  const service = sanitize(body.service, MAX_FIELD_LEN.service);
  const budget  = sanitize(body.budget,  MAX_FIELD_LEN.budget);
  const message = sanitize(body.message, MAX_FIELD_LEN.message);

  /* Validate required fields */
  if (!name || name.length < 2)         return { statusCode: 400, headers: cors, body: JSON.stringify({ ok: false, field: 'name' }) };
  if (!validEmail(email))                return { statusCode: 400, headers: cors, body: JSON.stringify({ ok: false, field: 'email' }) };
  if (!service)                           return { statusCode: 400, headers: cors, body: JSON.stringify({ ok: false, field: 'service' }) };
  if (!message || message.length < 10)   return { statusCode: 400, headers: cors, body: JSON.stringify({ ok: false, field: 'message' }) };

  /* ── Send via Zoho SMTP ── */
  const transporter = nodemailer.createTransport({
    host:   'smtp.zoho.com',
    port:   587,
    secure: false,       // STARTTLS
    auth: {
      user: process.env.ZOHO_USER,
      pass: process.env.ZOHO_PASS,  // Zoho App Password
    },
    tls: { rejectUnauthorized: true },
  });

  const mailOptions = {
    from:    `"Tech Velocity Site" <${process.env.ZOHO_USER}>`,
    to:      process.env.TO_EMAIL,
    replyTo: email,  // safe — already sanitized above
    subject: `[TV Contact] ${service} inquiry from ${name}`,
    text: [
      `Name:    ${name}`,
      `Email:   ${email}`,
      `Company: ${company || 'N/A'}`,
      `Service: ${service}`,
      `Budget:  ${budget  || 'N/A'}`,
      '',
      `Message:\n${message}`,
    ].join('\n'),
  };

  try {
    await transporter.sendMail(mailOptions);
    /* OWASP A09 — log event (no PII in CloudWatch) */
    console.log(JSON.stringify({ event: 'contact_sent', service, ts: new Date().toISOString() }));
    return { statusCode: 200, headers: cors, body: JSON.stringify({ ok: true }) };
  } catch (err) {
    console.error(JSON.stringify({ event: 'contact_error', msg: err.message }));