A simple contact form that submits data directly to RESTHeart Cloud using native HTML form submission with optional JavaScript enhancements for better error handling and user experience.
- Works without JavaScript - Uses native HTML form submission
- Progressive Enhancement - Optional JavaScript for better UX
- HTML5 form validation
- RESTHeart Cloud integration
application/x-www-form-urlencodedcontent type- Responsive design
- AJAX submission when JavaScript is enabled
- Success/error notifications (with JavaScript)
- Loading states (with JavaScript)
- A RESTHeart Cloud instance (get started at cloud.restheart.com)
- A web server to serve the HTML file (or use the included dev server)
-
Register at RESTHeart Cloud
- Go to cloud.restheart.com and create an account
-
Create a Free Service
- Create a new free service instance
- You'll receive a URL like:
https://acac36.eu-central-1-free-1.restheart.com
-
Configure the Service URL
- Open
config.jsin your code editor - Replace the empty string with your RESTHeart Cloud service URL:
const RESTHEART_SERVICE_URL = "https://your-instance.eu-central-1-free-1.restheart.com";
- Open
-
Generate Admin JWT
- From the RESTHeart Cloud admin webapp, generate an admin JWT token
-
Run the Setup Page
- Open
setup.htmlin your browser - The page will display your configured service URL
- Enter your admin JWT token
- Click "Setup Backend" to automatically configure:
/_schemascollection- Contact schema with email validation
/contactscollection with JSON Schema validation- Permission for unauthenticated POST requests with automatic timestamps
- Open
If you prefer to set up manually or need to customize the configuration:
Create a _schemas collection to store JSON schemas.
Create a document in /_schemas with _id: "contact":
{
"_id": "contact",
"type": "object",
"properties": {
"_id": {
"_$oid": "string"
},
"email": {
"type": "string",
"format": "email"
},
"message": {
"type": "string"
},
"timestamp": {
"type": "object",
"properties": {
"_$date": {
"type": "number"
}
},
"required": ["$date"],
"additionalProperties": false
},
"_etag": {
"_$oid": "string"
}
},
"required": ["email", "message", "timestamp"],
"additionalProperties": false
}Create a /contacts collection with JSON Schema validation:
PUT /contacts
{
"jsonSchema": {
"schemaId": "contact"
}
}Create a permission document in /acl to allow unauthenticated POST requests:
{
"_id": "allow-contact-form-post",
"predicate": "path(/contacts) and method(post)",
"priority": 20,
"roles": ["$unauthenticated"],
"mongo": {
"mergeRequest": {
"timestamp": "@now"
}
}
}This permission:
- Allows unauthenticated users to POST to
/contacts - Automatically adds a server-side timestamp using
@now
Edit index.html and update the form's action attribute with your RESTHeart Cloud URL:
<form action="https://your-instance.restheart.cloud/contact" method="POST" enctype="application/x-www-form-urlencoded">Replace https://your-instance.restheart.cloud/contact with your actual endpoint.
You can use any static file server. The simplest option:
# Using the built-in script (uses npx serve)
npm run devOr use any other static server:
# Using Python
python -m http.server 8080
# Using Node.js http-server
npx http-server
# Using PHP
php -S localhost:8080Or simply open index.html directly in your browser (though a web server is recommended for testing).
Navigate to http://localhost:8080 (or the appropriate port) and submit the form.
plain-js-contact-form/
├── index.html # Main HTML file with form
├── assets/
│ ├── styles.css # Styling
│ └── app.js # Optional JavaScript enhancements
├── package.json # Project metadata and scripts
└── README.md # This file
This application follows the progressive enhancement principle:
-
Base Layer (HTML): Form works with just HTML
- Native form submission to RESTHeart Cloud
- HTML5 validation
- Works even if JavaScript is disabled or fails to load
-
Enhancement Layer (JavaScript): When JavaScript is available:
- AJAX submission (no page reload)
- Better error handling with user-friendly messages
- Success notifications
- Loading indicators
- Form stays on the same page
The form uses standard HTML form submission:
<form action="https://your-instance.restheart.cloud/contact"
method="POST"
enctype="application/x-www-form-urlencoded">
<input type="email" name="email" required>
<textarea name="message" required></textarea>
<button type="submit">Send Message</button>
</form>When submitted, the browser:
- Validates fields using HTML5 validation
- Sends data as
application/x-www-form-urlencoded - Navigates to the server's response page
When assets/app.js loads, it:
- Intercepts form submission with
preventDefault() - Sends data via AJAX (fetch API)
- Displays success/error messages on the same page
- Shows loading indicators
- Clears the form on success
- No page reload required
The client sends:
email: Email address (validated as email format)message: The message text
The server adds:
_id: Auto-generated MongoDB ObjectIdtimestamp: Server-side timestamp with$datefield
- Network errors: Displayed in error alert
- Server errors: Error message extracted from response
- Validation errors: Caught before submission
- User-friendly error messages
- HTML5 validation before submission
- Browser handles network errors
- Server response determines what user sees
Modify assets/styles.css to customize the appearance. CSS variables are defined at the top:
:root {
--primary-color: #4a90e2;
--primary-hover: #357abd;
--success-color: #27ae60;
--error-color: #e74c3c;
/* ... more variables */
}Update the action attribute in the form tag in index.html:
<form action="https://your-custom-endpoint.com/contact" method="POST" enctype="application/x-www-form-urlencoded">To test or use the form without JavaScript, simply remove or comment out the script tag in index.html:
<!-- <script src="assets/app.js"></script> -->Submits a contact form message.
Request:
- Content-Type:
application/x-www-form-urlencoded - Body parameters:
email(string, email format): Email addressmessage(string): Message text
Response:
200 OK: Message successfully saved400 Bad Request: Validation error500 Internal Server Error: Server error
- All modern browsers and older browsers
- Works with JavaScript disabled
- HTML5 form validation
- CSS3 for styling
- Modern browsers supporting:
async/awaitfetchAPI- ES6+ features
- Chrome, Firefox, Safari, Edge (recent versions)
This example demonstrates progressive enhancement:
- Accessibility: Works for users with JavaScript disabled
- Resilience: Gracefully degrades if JavaScript fails
- Performance: Core functionality works immediately
- User Experience: Enhanced features when available
- Best Practice: Follows web standards
MIT License - feel free to use this code for your own projects!