replace zammad contact form with custom form via support-server

Use mCaptcha (self-hosted PoW captcha) + rate limiting for spam protection.
Form submissions send email confirmation to customer and CC support@start9.com.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Matt Hill
2026-02-19 09:03:19 -07:00
parent 874e31531b
commit 5face160ee
3 changed files with 95 additions and 41 deletions

View File

@@ -1,54 +1,62 @@
module.exports = { module.exports = {
url: 'https://start9.com', url: "https://start9.com",
torUrl: 'http://privacy34kn4ez3y3nijweec6w4g54i3g54sdv7r5mr6soma3w4begyd.onion', torUrl:
"http://privacy34kn4ez3y3nijweec6w4g54i3g54sdv7r5mr6soma3w4begyd.onion",
pitch: { pitch: {
url: '#infographics' url: "#infographics",
}, },
banner: false, banner: false,
products: { products: {
buyUrl: 'https://store.start9.com', buyUrl: "https://store.start9.com",
diyUrl: 'https://docs.start9.com/0.3.5.x/diy', diyUrl: "https://docs.start9.com/0.3.5.x/diy",
servers: 'https://store.start9.com/collections/servers', servers: "https://store.start9.com/collections/servers",
gear: 'https://store.start9.com/collections/apparel' gear: "https://store.start9.com/collections/apparel",
}, },
bitcoin: { bitcoin: {
whyRunBitcoinUrl: 'https://bitcoinmagazine.com/culture/six-reasons-you-should-run-bitcoin-node', whyRunBitcoinUrl:
whyRunLightningUrl: '', "https://bitcoinmagazine.com/culture/six-reasons-you-should-run-bitcoin-node",
whyRunLightningUrl: "",
}, },
beYourOwn: { beYourOwn: {
url: 'https://marketplace.start9.com' url: "https://marketplace.start9.com",
}, },
poweredBy: { poweredBy: {
url: 'https://github.com/Start9Labs/start-os' url: "https://github.com/Start9Labs/start-os",
}, },
support: { support: {
url: 'https://docs.start9.com/0.3.5.x/support' url: "https://docs.start9.com/0.3.5.x/support",
}, },
docs: { docs: {
url: 'https://docs.start9.com' url: "https://docs.start9.com",
}, },
dev: { dev: {
docs: 'https://docs.start9.com/0.3.5.x/developer-docs', docs: "https://docs.start9.com/0.3.5.x/developer-docs",
github: 'https://github.com/Start9Labs', github: "https://github.com/Start9Labs",
marketplace: 'https://marketplace.start9.com' marketplace: "https://marketplace.start9.com",
}, },
contribute: { contribute: {
url: 'https://start9.com/latest/contribute', url: "https://start9.com/latest/contribute",
techDetails: 'https://blog.start9.com/community-tech-program/' techDetails: "https://blog.start9.com/community-tech-program/",
}, },
footer: { footer: {
copyright: '© ' + new Date().getFullYear() + ' by Start9 Labs, Inc', copyright: "© " + new Date().getFullYear() + " by Start9 Labs, Inc",
canary: 'We have never received a secret government request to hand over user information.', canary:
donate: 'https://donate.start9.com' "We have never received a secret government request to hand over user information.",
donate: "https://donate.start9.com",
},
mcaptcha: {
// Widget URL from mCaptcha dashboard (Dashboard > Sitekeys > Widget Link)
widgetUrl:
"https://mcaptcha.start9.me/widget/?sitekey=VXoIaUB6OaX7JtkF4RlGt05CXyH7k1k4",
}, },
media: { media: {
// NOTE: the keys here correspond to the name of the svg logo // NOTE: the keys here correspond to the name of the svg logo
matrix: 'https://matrix.to/#/#developer-space:matrix.start9labs.com', matrix: "https://matrix.to/#/#developer-space:matrix.start9labs.com",
support: 'https://start9.me', support: "https://start9.me",
twitter: 'https://x.com/start9labs', twitter: "https://x.com/start9labs",
youtube: 'https://www.youtube.com/channel/UCGEw4HJDvOn3Oy8ykR36P7Q', youtube: "https://www.youtube.com/channel/UCGEw4HJDvOn3Oy8ykR36P7Q",
discourse: 'https://community.start9.com', discourse: "https://community.start9.com",
medium: 'https://start9labs.medium.com', medium: "https://start9labs.medium.com",
ghost: 'https://blog.start9.com', ghost: "https://blog.start9.com",
}, },
}; };

View File

@@ -436,7 +436,7 @@ section#contact {
margin-bottom: 24px; margin-bottom: 24px;
} }
.zammad-form { .contact-form {
font-size: 18px; font-size: 18px;
input { input {

View File

@@ -35,19 +35,65 @@ layout: layouts/peripheral.njk
<li> <li>
<h3>Message Us</h3> <h3>Message Us</h3>
<p>Response times are usually between 24-48 hours. For faster support, use one of the options above</p> <p>Response times are usually between 24-48 hours. For faster support, use one of the options above</p>
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script> <div class="contact-form">
<div id="feedback-form">form will be placed in here</div> <form id="contact-form">
<label for="contact-name">Name</label>
<script id="zammad_form_script" src="https://zammad.start9labs.com/assets/form/form.js"></script> <input id="contact-name" class="form-control" type="text" placeholder="Your name" required />
<label for="contact-email">Email</label>
<input id="contact-email" class="form-control" type="email" placeholder="Your email" required />
<label for="contact-message">Message</label>
<textarea id="contact-message" class="form-control" rows="5" placeholder="How can we help?" required></textarea>
<label data-mcaptcha_url="{{ site.mcaptcha.widgetUrl }}" for="mcaptcha__token" id="mcaptcha__token-label"></label>
<div id="mcaptcha__widget-container"></div>
<input type="hidden" name="mcaptcha__token" id="mcaptcha__token" />
<button type="submit">Submit</button>
</form>
<script src="https://unpkg.com/@mcaptcha/vanilla-glue@0.1.0-rc2/dist/index.js"></script>
<div id="contact-success" class="form-alert form-alert--success"></div>
<div id="contact-error" class="form-alert form-alert--error"></div>
</div>
<script> <script>
$(function() { document.getElementById('contact-form').addEventListener('submit', async function(e) {
$('#feedback-form').ZammadForm({ e.preventDefault();
messageTitle: 'Start9 Contact Form', const form = e.target;
messageSubmit: 'Submit', const success = document.getElementById('contact-success');
messageThankYou: 'Inquiry received! We will get back to you ASAP.', const error = document.getElementById('contact-error');
attachmentSupport: true
}); success.classList.remove('form-alert--visible');
error.classList.remove('form-alert--visible');
const captchaToken = document.getElementById('mcaptcha__token').value;
if (!captchaToken) {
error.textContent = 'Please complete the captcha.';
error.classList.add('form-alert--visible');
return;
}
const body = {
name: document.getElementById('contact-name').value,
email: document.getElementById('contact-email').value,
message: document.getElementById('contact-message').value,
mcaptcha__token: captchaToken,
};
try {
const res = await fetch('https://start9.me/_api/contact', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(body),
});
if (res.ok) {
form.reset();
success.textContent = 'Inquiry received! We will get back to you within 24 hours.';
success.classList.add('form-alert--visible');
} else {
throw new Error();
}
} catch {
error.innerHTML = "Something went wrong. If this persists, try us on <a href='https://matrix.to/#/#general:start9.me' rel='noopener noreferrer' target='_blank'>Matrix</a> instead.";
error.classList.add('form-alert--visible');
}
}); });
</script> </script>
</li> </li>