HTMX on Cloudflare Pages

HTMX on Cloudflare Pages

cloudflare pages HTMX

Using HTMX and Cloudflare Workers is a great way to sprinkle in some dynamic functionality into your Cloudflare Pages static site. Let’s look at an example of handling a form submission.

Important! Before proceeding with adding HTMX to your Cloudflare Pages site, please make sure you’ve properly secured your site from XSS attacks. For a starter guide on this topic see our post Adding Security Headers on Cloudflare Pages

Cloudflare Wrangler Config

First step is to make sure you have Cloudflare Wrangler installed to be able to test your Cloudflare Worker locally (install directions can be found here).

Now let’s create a ‘wrangler.toml’ file in the base directory of your project. This configuration file lets Wrangler know how to load your site.

# wrangler.toml
name = "example"
pages_build_output_dir = "public"

Explanation of Settings

Next make sure any Cloudflare Worker scripts you want to run are within a ‘/functions’ folder within your site’s root directory. Then run the below command to have Wrangler load your site. Default will for your site to be at http://localhost:8788.

npx wrangler pages dev

Note: This will live reload changes to your files in ‘/functions’ but not in the ‘pages_build_output_dir’ path.

Using HTMX

As an example, let’s create an email submission form using HTMX.

Firstly, add a form to the static page using the HTMX ‘hx-post’ directive. Here, we’re also including the form’s ‘action’ attribute as well to provide progressive enhancement.

<form action="/emailList" hx-post="/emailList">
	<input type="email" name="email" placeholder="Enter your email">
	<button class="button" type="submit">Get Notified</button>
</form>

On the static webpage that includes the email form include a HTML head script link to HTMX.

It’s strongly advised to include a ’nonce’ for this file to help guard against XSS attacks. See “Option 2” on Adding Security Headers on Cloudflare Pages

<head>
	<script src="/path-to-HTMX/htmx.min.js"></script>
</head>

Lastly, create a new Cloudflare Worker at ‘/functions/emailList’.

Cloudflare Pages uses file based routing for the ‘/functions’ folder. Meaning that Pages will automatically route requests to ‘/emailList’ to your function ‘/functions/emailList’. Hence, why the HTML form above is posting to ‘/emailList’.

Below is an example of a Cloudflare Worker that expects to receive an email address form submission, stores in a database, and then returns a HTML snippet.

Reminder: Don’t forget to sanitize user provided data before storing in your database. You’ll thank me later :)

export async function onRequest(context) {

	// Initialize variables.
	const { request, env } = context
	
	// Check if the request is an OPTIONS request.
	if (request.method === 'OPTIONS') {

		// Respond with headers that indicate which HTTP methods are allowed.
		return new Response(null, { 
			headers: { 
				'Allow': 'POST, OPTIONS' 
			}, 
			status: 204 
		})
	}

	// Check if the request is a POST request.
	if (request.method === 'POST') {

		// Get the form data.
		const formData = await request.formData()

		// Get the email from the form data.
		const email = formData.get('email')
		
		// Handle your form data here (e.g., send an email, store in a database, etc.)
		console.log(`Email received: ${email}`)
		
		// Return whatever content you want HTMX to replace the form with.
		return new Response("Thank-you! We've saved your email address.", { status: 200 })
	}
	
	return new Response('Method not allowed', { status: 405 })
}

Note that in the above example we’re handling both ‘OPTIONS’ and ‘POST’ methods. That’s because HTMX will issue an ‘OPTIONS’ request prior to sending a ‘POST’ to make sure the server will accept a ‘POST’ method for the path.

Congratulations! You now have a dynamic form on your static Cloudflare Pages website.

Cheers 🥂

More Articles