In this Astro comment form post, we are going to explore the new Hybrid Rendering pattern introduced in Astro 2.0. As well as that, we integrate Cloudflare’s innovative Captcha. It is like no other Captcha you have seen before! Prerendering improves the developer experience, making adding a form handler to an otherwise static site a lot easier. Turnstile improves user experience and saves visitors having to solve a string of Captcha challenges, while still protecting our site from bots.
Two modern patterns for building websites are Server-side rendering (SSR) and Static Site Generation (SSG). With SSR, each time a visitor loads a web page on their device, the page is generated (from scratch) on a remote server and sent to their device. With SSG, we create all the pages beforehand, and the visitor device instead loads the pre-built page. SSG offers security and speed benefits. On the other hand, SSR makes it easier to customize the page to each visitor (letting a visitor see posts only from friends in a social sharing app as an example).
Before Astro 2, you had to choose either SSG or SSR for the whole site. Those days are now gone and now Astro lets you pick and choose which pages you want to be SSG and which SSR. A bonus is that you can keep the whole site SSG (for speed and security benefits) but use the SSR features to add a form handler. A form handler is just server code to read in form inputs and process them. Hybrid rendering works by setting the default to SSR. We must then override that default for each individual page we want to generate statically or prerender.
Captchas are the challenges sites use to check you are not a robot! Using proprietary technology, Cloudflare are able to tell bots apart from human users without solving complex puzzles which can present accessibility issues for some users and irritate others.
In this post, we build up a basic comment form component. You could use this as a starting point for a more sophisticated comment form on a blog site.
As mentioned above, we will create a comment form component. This will be fairly basic, as the main objective is to see how to add Turnstile and how Astro hybrid rendering work. For your own project, you will want to incorporate server side sanitization, and validation as well as, perhaps, some client-side user interface progressive enhancements.
You will need a Cloudflare account to use Turnstile . At the time of writing, it is in beta and access is free. Log into the Cloudflare console and select Turnstile from the menu on the left. Next, click the Add site button. Turnstile credentials can be limited to work from one or more site domains. We will generate credentials for localhost (as the domain), for testing locally. When you deploy your site, generate a new set of credentials for your public domain.
For now, enter
Localhost in the Site name field
localhost in the Domain field. I chose the Non-interactive option for Widget type, but choose whatever best matches your own needs.
If you have an existing site you want to try this code on, create a git branch and follow along. If, instead, you are starting from scratch, spin up a new Astro app:
Because our form handler will run in SSR mode, we need to pick a cloud provider, so Astro can customize the build for it. We select Cloudflare here. We will use Svelte for the form markup, though you could probably get away with just an Astro component if you really wanted to.
I chose the default options in the CLI prompts. Once the dev server starts, it will let you know
the URL it is listening on. By default, this will be
If you take a look at
astro.config.mjs you should see something
13 is important here; it tells Astro to build the whole site
as an SSR app. We will override this on our pages, and in fact only the form handler will be
managed by the server.
Add your Turnstile credentials to a new
.env file in the project
root directory. Remember not to commit these to your git repo:
PUBLIC_SITE_URL to wherever your site is running. You
can use the commented out value later when running a Cloudflare preview locally.
Next, we write some Astro code 🧑🏽🚀.
Replace the content in
5 is where we tell Astro we want to prerender this page,
overriding the SSR default set in
astro.config.mjs. Astro will
generate a static page which can be cached by a global CDN.
I like to use import path aliases (so we have
~/layouts/Layout.astro instead of
../layouts/Layout.astro in line
3). For this to work update
tsconfig.json in the project root
You might notice we referenced some CSS custom properties in the Astro file above. We can define
those in a global CSS file and import them to the existing
src/layouts/Layout.astro file. That way, the custom properties will be available to us in any pages which use the
layout. Update the layout file:
src/styles/ folder, then add a
global.css file with the following content:
src/styles/global.css — click to expand code.
We are still missing the CSS for the fonts. Create
the same folder:
src/styles/fonts.css — click to expand code.
For this to work, we will serve the
.woff2 files from our project. You can download them and save the four files (
700 weight), to a
public/fonts directory in the project.
We now have the basics out of the way. Hope that wasn’t too quick! Drop a comment below if something needs more explanation. Next we will add the Svelte form component. Then, finally, we can add the SSR form handler.
We will add a script tag to the page html
head section for
Turnstile. Svelte makes it quite easy to do this from within the component. That helps us
encapsulate all the client-site Turnstile code in a single file. Create
CommentForm.svelte in the
src/components directory with the following content:
You see the Turnstile code we needed to add is minimal. We add a script tag in the HTML head
7). Then, the little widget which shows up below the
submit button (line
form. You will see the form has
as the action. That is the route we will set the form handler to listen on.
Spruce up the form a touch with some extra styles at the bottom of
src/components/CommentForm.svelte — click to expand code.
Before we jump to the form handler, let’s add a thank-you page. We will show this on
successful form completion. Create
We are on the home straight now. Once we add the form handler, all we will have left to do is
test! In Astro, API routes follow the same file-based routing system as HTML pages. The main
difference is that the file extensions are different. Create a
src/pages/api folder and in there, add
message.ts with the following content:
extra form field for us? We pull this in, in line
12. The final
part of the verification process is to send the client response to Cloudflare, along with our
secret Turnstile API key. The server replies with a JSON object including a
success field. As you might expect, this is
false when Turnstile
assesses the visitor to be a bot and
In a real world app, when
true we would want to commit the comment data to our database as well as any other processing
needed. We just do a console log here instead. Also, in a production app, we should want to do
some sanitization before inserting the data to the database. On top, we would have some
validation, so we do not commit junk to the database. If the comments will be displayed publicly,
you will also need to filter them, checking for inappropriate user-submitted content.
Returning to our basic example, finally we respond with a redirect pushing the visitor browser to
our new Thank-You page (line
Try submitting the form from your dev server. If all goes well, you should see the Thank-You page.
To build the site locally, we need to run in a Cloudflare wrangler environment. Add an extra
script to the project
package.json file to handle this:
Then run the script from the Terminal:
This time, the site will be available at
this is your first time running wrangler from your machine, follow the instructions in the
Terminal to log in.
Remember to update
PUBLIC_SITE_URL in your
.env file to match the new URL (otherwise, the form will not submit as expected).
That’s it! You can now try pushing to Cloudflare Pages. Create a set of Turnstile credentials for your actual public domain first.
In this post, we saw how you can add a server-side form handler to your static Astro site. In particular, we saw:
- how to add Turnstile Captcha in Astro
- how Astro Hybrid rendering and prerendering work
- some points to consider in a full production comment form
You can see the full code for this project in the Rodney Lab GitHub repo . I do hope you have found this post useful! I am keen to hear what you are doing with Astro and ideas for future projects. Also, let me know about any possible improvements to the content above.
- Hybrid Rendering is a technique popularized by Astro which lets you choose between two rendering methods on a page-by-page basis. The two options are SSG (Static Site Generation) and SSR (Server-Side Generation). SSG is great for content or information sites. You generate all the pages ahead of time and serve them from a global CDN. This offer speed and better security. Generally, every visitor will see the same content, so SSG is not great for apps where the user logs in and sees a curated feed. SSR is great in this case though. With SSR, the pages are generated just in time, so it is easy to customize them for each visitor. You can use Hybrid rendering even if you want all your pages to be statically generated (or prerendered) but also want to have interactive forms on the site. Interactive forms (a comment form, for example) require a server to process the entered data. Hybrid rendering can help here. You keep all pages static to gain the speed and security benefits, but have a server-based form handler to sanitize, form inputs and add them to your database.
- Captchas are challenges on websites used to tell bots apart from regular human users. Traditionally, the challenges were interactive, and the user had to click images with traffic lights or some similar task supposed to be difficult for artificial intelligence to perform. Some of these interactive challenges pose accessibility issues and some users find them annoying. Turnstile is non-interactive. It is able to distinguish human from bot visitors in the background. In so doing, it addresses those drawbacks
- Astro makes this possible. In the past, to add form processing to a static or JAMStack site, you would add serverless functions. These could run in different environments, and typically their code was segregated from the rest of your project. Hybrid rendering in Astro lets you prerender all your site pages, but include a server handler to process the form inputs. We saw an example, creating a comment form. Now your form handling code becomes a first-class in your project!
Have you found the post useful? Would you prefer to see posts on another topic instead? Get in touch with ideas for new posts. Also, if you like my writing style, get in touch if I can write some posts for your company site on a consultancy basis. Read on to find ways to get in touch, further below. If you want to support posts similar to this one and can spare a few dollars, euros or pounds, please consider supporting me through Buy me a Coffee.
Amazed by 🚀 Astro 2.0's Hybrid Rendering. It lets you add server form handlers to a static site.— Rodney (@askRodney) February 1, 2023
Just dropped a new post where we do just that. Also use Cloudflare Turnstile Captcha.
Hope you find it useful!
#JAMStack #learnastro #useThePlatformLukehttps://t.co/9DTAycIRMz pic.twitter.com/SCLOYXgP81
Finally, feel free to share the post on your social media accounts for all your followers who will find it useful. As well as leaving a comment below, you can get in touch via @askRodney on Twitter, @[email protected] on Mastodon and also the #rodney Element Matrix room. Also, see further ways to get in touch with Rodney Lab. I post regularly on Astro as well as SEO. Also, subscribe to the newsletter to keep up-to-date with our latest projects.