Skip to Content
ExamplesHugo Integration

Hugo Integration

Hugo is a fast static site generator. This guide shows you how to add Kollect forms to your Hugo site.

Basic Contact Form

Create a contact page template:

<!-- layouts/contact/single.html --> {{ define "main" }} <div class="contact-page"> <h1>{{ .Title }}</h1> <form action="https://kollect.app/f/YOUR_FORM_KEY" method="POST" class="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="5" required></textarea> </div> <button type="submit">Send Message</button> </form> </div> {{ end }}

Using Shortcodes

Create a reusable contact form shortcode:

<!-- layouts/shortcodes/contact-form.html --> <form action="https://kollect.app/f/{{ .Get "key" }}" method="POST" class="kollect-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="5" required></textarea> </div> <button type="submit">{{ .Get "submit" | default "Submit" }}</button> </form>

Use in your content:

<!-- content/contact.md --> --- title: Contact Us --- ## Get in Touch {{< contact-form key="YOUR_FORM_KEY" submit="Send Message" >}}

Newsletter Signup Shortcode

<!-- layouts/shortcodes/newsletter.html --> <div class="newsletter-signup"> <form action="https://kollect.app/f/{{ .Get "key" }}" method="POST" class="newsletter-form"> <input type="email" name="email" placeholder="{{ .Get "placeholder" | default "Enter your email" }}" required > <button type="submit">{{ .Get "submit" | default "Subscribe" }}</button> </form> </div>

Use in templates or content:

{{ with .Site.Params.newsletterFormKey }} {{< newsletter key=. submit="Subscribe" placeholder="Your email address" >}} {{ end }}

Configuration with Config File

Store form keys in your configuration:

# config.toml [params] contactFormKey = "your_contact_form_key" newsletterFormKey = "your_newsletter_form_key"

Or in YAML:

# config.yaml params: contactFormKey: "your_contact_form_key" newsletterFormKey: "your_newsletter_form_key"

Use in templates:

<form action="https://kollect.app/f/{{ .Site.Params.contactFormKey }}" method="POST"> <!-- form fields --> </form>

Advanced Form with Validation

<!-- layouts/partials/advanced-form.html --> <form action="https://kollect.app/f/{{ .Site.Params.contactFormKey }}" method="POST" id="contact-form" class="contact-form" > <div class="form-group"> <label for="name">Name *</label> <input type="text" id="name" name="name" required minlength="2" > <span class="error-message" data-error="name"></span> </div> <div class="form-group"> <label for="email">Email *</label> <input type="email" id="email" name="email" required > <span class="error-message" data-error="email"></span> </div> <div class="form-group"> <label for="phone">Phone</label> <input type="tel" id="phone" name="phone" pattern="[0-9]{10}" > <span class="error-message" data-error="phone"></span> </div> <div class="form-group"> <label for="subject">Subject *</label> <select id="subject" name="subject" required> <option value="">Choose a subject</option> <option value="general">General Inquiry</option> <option value="support">Support</option> <option value="sales">Sales</option> </select> </div> <div class="form-group"> <label for="message">Message *</label> <textarea id="message" name="message" rows="5" required minlength="10" ></textarea> <span class="error-message" data-error="message"></span> </div> <button type="submit" id="submit-btn"> <span class="btn-text">Send Message</span> <span class="btn-loading" style="display: none;">Sending...</span> </button> <div id="form-status" style="display: none;"></div> </form> <script> document.getElementById('contact-form').addEventListener('submit', async function(e) { e.preventDefault(); const form = e.target; const submitBtn = document.getElementById('submit-btn'); const btnText = submitBtn.querySelector('.btn-text'); const btnLoading = submitBtn.querySelector('.btn-loading'); const statusDiv = document.getElementById('form-status'); // Disable submit button submitBtn.disabled = true; btnText.style.display = 'none'; btnLoading.style.display = 'inline'; try { const response = await fetch(form.action, { method: 'POST', body: new FormData(form) }); if (response.ok) { statusDiv.textContent = 'Thank you! Your message has been sent.'; statusDiv.className = 'success-message'; statusDiv.style.display = 'block'; form.reset(); } else { throw new Error('Submission failed'); } } catch (error) { statusDiv.textContent = 'Oops! Something went wrong. Please try again.'; statusDiv.className = 'error-message'; statusDiv.style.display = 'block'; } finally { submitBtn.disabled = false; btnText.style.display = 'inline'; btnLoading.style.display = 'none'; } }); </script>

File Upload Form

<!-- layouts/partials/file-upload-form.html --> <form action="https://kollect.app/f/{{ .Site.Params.uploadFormKey }}" method="POST" enctype="multipart/form-data" > <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="resume">Resume (PDF only)</label> <input type="file" id="resume" name="resume" accept=".pdf" required > <small>Maximum file size: 10MB</small> </div> <button type="submit">Submit Application</button> </form>

Multi-Step Form

<!-- layouts/partials/multi-step-form.html --> <div class="multi-step-form"> <div class="progress-bar"> <div class="step active" data-step="1">1. Personal Info</div> <div class="step" data-step="2">2. Details</div> <div class="step" data-step="3">3. Review</div> </div> <form action="https://kollect.app/f/{{ .Site.Params.contactFormKey }}" method="POST" id="multi-step-form"> <!-- Step 1 --> <div class="form-step active" data-step="1"> <h3>Personal Information</h3> <div class="form-group"> <label for="firstName">First Name</label> <input type="text" id="firstName" name="firstName" required> </div> <div class="form-group"> <label for="lastName">Last Name</label> <input type="text" id="lastName" name="lastName" required> </div> <div class="form-group"> <label for="email">Email</label> <input type="email" id="email" name="email" required> </div> <button type="button" class="next-btn" data-next="2">Next</button> </div> <!-- Step 2 --> <div class="form-step" data-step="2"> <h3>Additional Details</h3> <div class="form-group"> <label for="company">Company</label> <input type="text" id="company" name="company"> </div> <div class="form-group"> <label for="message">Message</label> <textarea id="message" name="message" rows="5"></textarea> </div> <button type="button" class="prev-btn" data-prev="1">Previous</button> <button type="button" class="next-btn" data-next="3">Next</button> </div> <!-- Step 3 --> <div class="form-step" data-step="3"> <h3>Review & Submit</h3> <div id="review-content"></div> <button type="button" class="prev-btn" data-prev="2">Previous</button> <button type="submit">Submit</button> </div> </form> </div> <script src="/js/multi-step-form.js"></script>

Styling

Add to your stylesheet:

/* assets/css/forms.css */ .contact-form { max-width: 600px; margin: 0 auto; } .form-group { margin-bottom: 1.5rem; } .form-group label { display: block; margin-bottom: 0.5rem; font-weight: 500; } .form-group input, .form-group textarea, .form-group select { width: 100%; padding: 0.75rem; border: 1px solid #ddd; border-radius: 4px; font-size: 1rem; } .form-group input:focus, .form-group textarea:focus, .form-group select:focus { outline: none; border-color: #8B5CF6; box-shadow: 0 0 0 3px rgba(139, 92, 246, 0.1); } button[type="submit"] { padding: 0.75rem 2rem; background: #8B5CF6; color: white; border: none; border-radius: 4px; cursor: pointer; font-size: 1rem; transition: background 0.2s; } button[type="submit"]:hover { background: #7C3AED; } button[type="submit"]:disabled { background: #ccc; cursor: not-allowed; } .success-message { padding: 1rem; background: #d4edda; border: 1px solid #c3e6cb; border-radius: 4px; color: #155724; margin-top: 1rem; } .error-message { padding: 1rem; background: #f8d7da; border: 1px solid #f5c6cb; border-radius: 4px; color: #721c24; margin-top: 1rem; }

Environment-Specific Keys

Use different form keys for development and production:

# config/_default/params.toml [forms] contact = "dev_form_key" # config/production/params.toml [forms] contact = "prod_form_key"

Integration with Hugo Pipes

Process forms with Hugo’s asset pipeline:

{{ $formJS := resources.Get "js/form-handler.js" | minify | fingerprint }} <script src="{{ $formJS.RelPermalink }}" integrity="{{ $formJS.Data.Integrity }}"></script>

Next Steps

Last updated on