A serverless form submission platform. Capture HTML form data from any website, optionally email it, and manage submissions through a modern dashboard. Built with the Noundry tooling ecosystem.
Three simple steps: create an endpoint, point your HTML form, and receive submissions.
<form action="https://forms.noundry.com/f/contact" method="POST">
<input type="text" name="name" required>
<input type="email" name="email" required>
<textarea name="message" required></textarea>
<button type="submit">Send</button>
</form><!-- Submissions are emailed directly -->
<form action="https://forms.noundry.com/f/you@example.com" method="POST">
<!-- Form fields -->
</form>Statistics, recent forms, submission tracking with IP, domain, and timestamps.
Optional email delivery via Mailgun for each form submission.
JavaScript helper for no-redirect submissions with custom success/error messages.
Built-in honeypot field support. Submissions with filled honeypot fields are silently rejected.
Export form submissions for analysis in spreadsheet applications.
GitHub authentication plus traditional username/password login.
POST /f/{slug}
Content-Type: application/x-www-form-urlencoded
| Field | Description |
|---|---|
_redirect_url | Custom URL to redirect after submission |
_subject | Custom email subject line |
_honeypot | Spam protection - submission rejected if filled |
_gotcha | Alternative honeypot field name |
{
"success": true,
"message": "Form submitted successfully.",
"redirectUrl": "https://...",
"submissionId": "guid"
}AJAX is detected via Accept: application/json header or X-Requested-With: XMLHttpRequest.
Include the helper script for AJAX form submissions without page redirects.
<script src="https://forms.noundry.com/js/noundry-forms.js"></script>
<form action="https://forms.noundry.com/f/contact"
method="POST"
data-noundry-form
data-success-message="Thanks! We'll be in touch."
data-error-message="Oops! Please try again.">
<!-- Form fields -->
</form>| Attribute | Description |
|---|---|
data-noundry-form | Enable AJAX submission (required) |
data-success-message | Custom success message |
data-error-message | Custom error message |
data-redirect | URL to redirect on success |
data-loading-text | Button text while submitting (default: "Sending...") |
data-on-success | Global function name to call on success |
data-on-error | Global function name to call on error |
form.addEventListener('noundry:success', (e) => {
console.log('Submission ID:', e.detail.submissionId);
});
form.addEventListener('noundry:error', (e) => {
console.log('Error:', e.detail.message);
});Add a hidden honeypot field to prevent bot submissions. Bots will fill it; humans will not.
<!-- Hidden honeypot - bots will fill this, humans won't -->
<div style="position: absolute; left: -9999px;">
<input type="text" name="_honeypot" tabindex="-1" autocomplete="off">
</div>Configure via environment variables in a .env file.
# Database (required)
DATABASE_CONNECTION_STRING=Host=localhost;Port=5432;Database=noundryforms;...
# OAuth (optional)
GITHUB_CLIENT_ID=your_github_client_id
GITHUB_CLIENT_SECRET=your_github_client_secret
# Email via Mailgun (optional)
MAILGUN_API_KEY=your_mailgun_api_key
MAILGUN_DOMAIN=your_mailgun_domain
MAIL_FROM_ADDRESS=forms@yourdomain.com
# Application
APP_BASE_URL=https://forms.yourdomain.comSecure password storage using BCrypt.Net-Next.
Anti-forgery tokens on all dashboard forms.
30 requests/minute per form endpoint, 100/minute global.
X-Content-Type-Options, X-Frame-Options, X-XSS-Protection headers applied.
Forms showcases the full Noundry ecosystem in a production application.
| Package | Purpose |
|---|---|
Noundry.Tuxedo | Lightweight ORM for PostgreSQL |
Noundry.Tuxedo.Bowtie | Schema migrations |
Noundry.Authnz | OAuth 2.0 authentication (GitHub) |
Noundry.DotEnvX | Environment variable loading |
Noundry.Guardian | Guard clauses and validation |
Noundry.Sanquhar | Email templating |
Noundry.UI | Pre-built UI components |
Noundry.Tailbreeze | Tailwind CSS v4 integration |
NoundryForms/
├── src/
│ └── NoundryForms.Web/
│ ├── Configuration/ # Settings classes
│ ├── DTOs/ # API response models
│ ├── Endpoints/ # Minimal API endpoints
│ ├── Models/ # Entity models (Account, Form, Submission)
│ ├── Services/ # Business logic
│ ├── EmailTemplates/ # Razor email templates
│ ├── Pages/ # Razor Pages (Dashboard, Forms, Submissions)
│ └── wwwroot/js/ # noundry-forms.js helper
├── tests/
│ └── NoundryForms.Tests/
├── docker-compose.yml
└── NoundryForms.sln# docker-compose.yml
version: '3.8'
services:
app:
build: ./src/NoundryForms.Web
ports:
- "5000:8080"
environment:
- DATABASE_CONNECTION_STRING=Host=db;Port=5432;...
depends_on:
- db
db:
image: postgres:16
environment:
- POSTGRES_DB=noundryforms
- POSTGRES_PASSWORD=your_password
volumes:
- postgres_data:/var/lib/postgresql/data$ docker-compose up -d