Guide

HTML Forms

Submit data to 1db using plain HTML and vanilla JavaScript.

The simplest way to integrate 1db is with a standard HTML form and a bit of JavaScript. This approach works with any website, regardless of framework.

Basic Example

Here's a complete, working contact form:

contact.html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Contact Form</title>
  <style>
    * { box-sizing: border-box; }
    body {
      font-family: system-ui, sans-serif;
      max-width: 500px;
      margin: 2rem auto;
      padding: 0 1rem;
    }
    .form-group { margin-bottom: 1rem; }
    label {
      display: block;
      margin-bottom: 0.5rem;
      font-weight: 500;
    }
    input, textarea {
      width: 100%;
      padding: 0.75rem;
      border: 1px solid #ddd;
      border-radius: 6px;
      font-size: 1rem;
    }
    input:focus, textarea:focus {
      outline: none;
      border-color: #7BAFD4;
      box-shadow: 0 0 0 3px rgba(123, 175, 212, 0.2);
    }
    button {
      width: 100%;
      background: #7BAFD4;
      color: white;
      padding: 0.875rem 1.5rem;
      border: none;
      border-radius: 6px;
      font-size: 1rem;
      font-weight: 500;
      cursor: pointer;
      transition: background 0.2s;
    }
    button:hover { background: #5a9bc4; }
    button:disabled { opacity: 0.6; cursor: not-allowed; }
    .error { color: #ef4444; font-size: 0.875rem; margin-top: 0.5rem; }
    .success {
      background: #10b981;
      color: white;
      padding: 1rem;
      border-radius: 6px;
      text-align: center;
    }
  </style>
</head>
<body>
  <h1>Contact Us</h1>

  <form id="contact-form">
    <div class="form-group">
      <label for="name">Name *</label>
      <input type="text" id="name" name="name" required>
    </div>

    <div class="form-group">
      <label for="email">Email *</label>
      <input type="email" id="email" name="email" required>
    </div>

    <div class="form-group">
      <label for="message">Message</label>
      <textarea id="message" name="message" rows="4"></textarea>
    </div>

    <button type="submit">Send Message</button>
    <div id="form-error" class="error" style="display: none;"></div>
  </form>

  <div id="success-message" class="success" style="display: none;">
    Thanks! We'll be in touch soon.
  </div>

  <script>
    const API_URL = "https://your-deployment.convex.site/v1/leads";
    const API_KEY = "1db_live_YOUR_API_KEY"; // Use a proxy in production!

    const form = document.getElementById("contact-form");
    const errorDiv = document.getElementById("form-error");
    const successDiv = document.getElementById("success-message");

    form.addEventListener("submit", async (e) => {
      e.preventDefault();

      const submitBtn = form.querySelector('button[type="submit"]');
      const originalText = submitBtn.textContent;

      // Reset state
      errorDiv.style.display = "none";
      submitBtn.disabled = true;
      submitBtn.textContent = "Sending...";

      // Gather form data
      const formData = new FormData(form);
      const data = Object.fromEntries(formData.entries());

      try {
        const response = await fetch(API_URL, {
          method: "POST",
          headers: {
            "Content-Type": "application/json",
            "X-API-Key": API_KEY,
          },
          body: JSON.stringify({
            formSlug: "contact-form", // Your form slug
            ...data,
          }),
        });

        if (!response.ok) {
          const error = await response.json();
          throw new Error(error.message || "Submission failed");
        }

        // Success!
        form.style.display = "none";
        successDiv.style.display = "block";

      } catch (error) {
        errorDiv.textContent = error.message || "Something went wrong.";
        errorDiv.style.display = "block";
      } finally {
        submitBtn.disabled = false;
        submitBtn.textContent = originalText;
      }
    });
  </script>
</body>
</html>

Security Warning

Never expose your API key directly in client-side code on production websites. The example above is fine for testing, but for production you should:

  • • Use a server-side proxy to add the API key
  • • Use serverless functions (Vercel, Netlify, Cloudflare)
  • • Or use our embed widget which handles auth for you

Secure Server Proxy

Here's how to create a simple proxy using serverless functions:

Vercel Edge Function

api/submit.ts
// /api/submit.ts (Vercel Edge Function)
export const config = { runtime: 'edge' };

export default async function handler(request: Request) {
  if (request.method !== 'POST') {
    return new Response('Method not allowed', { status: 405 });
  }

  const body = await request.json();
  const { formSlug, ...data } = body;

  const response = await fetch(
    "https://your-deployment.convex.site/v1/leads",
    {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        "X-API-Key": process.env.ONEDB_API_KEY,
      },
      body: JSON.stringify({
        formSlug: formSlug || "contact-form",
        ...data,
      }),
    }
  );

  const result = await response.json();

  return new Response(JSON.stringify(result), {
    status: response.status,
    headers: { "Content-Type": "application/json" },
  });
}

Then update your form to use the proxy:

javascript
// Update your form submission
const response = await fetch("/api/submit", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({
    form: "contact-form",
    data: formData,
  }),
});

Client-Side Validation

Add validation before submission for better UX:

javascript
function validateForm(data) {
  const errors = {};

  if (!data.name || data.name.trim().length < 2) {
    errors.name = "Name must be at least 2 characters";
  }

  if (!data.email || !isValidEmail(data.email)) {
    errors.email = "Please enter a valid email";
  }

  return {
    isValid: Object.keys(errors).length === 0,
    errors,
  };
}

function isValidEmail(email) {
  return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
}

// Use in your submit handler:
form.addEventListener("submit", async (e) => {
  e.preventDefault();

  const formData = new FormData(form);
  const data = Object.fromEntries(formData.entries());

  const { isValid, errors } = validateForm(data);

  if (!isValid) {
    // Show errors next to fields
    Object.entries(errors).forEach(([field, message]) => {
      const errorEl = document.getElementById(`${field}-error`);
      if (errorEl) errorEl.textContent = message;
    });
    return;
  }

  // Continue with submission...
});

Next Steps