Form Handling for Jamstack Sites Using Cloudflare Workers – SitePoint

In this tutorial, you’ll learn how to build a form-handling service for your Jamstack website or single page application (SPA) using Cloudlflare Workers.
With Jamstack technology, HTML code is rendered at build time and then deployed to edge servers. This allows very fast load times for end users. In addition, businesses benefit by paying much significantly lower hosting fees.
One issue with Jamstack technology is how to deal with site features that can only be implemented with server-side technologies. For example, form handling is relatively easy if you have access to a server-side technology like PHP, where you can just use mail(, , ) to collect and send mail data.
Of course, Jamstack sites aren’t left out in the cold. You can run back-end applications on a Jamstack site using serverless computing. But you’ll need to implement a microservice architecture in your back-end development. Serverless computing requires that you build your logic into loosely coupled, independently deployable services.
Serverless computing can be a lot more cost-effective than renting private servers often needed for running back-end apps. An added bonus of serverless computing is that you can start to create more complicated workflows using further services (such as using services like Airtable to store form data).
For this tutorial, you’ll learn how to build and deploy a form-handling service for a React front-end SPA. Technically, any front-end framework will do. We’ll use Cloudflare Workers to develop our serverless function. Before we start working on the code, let’s first have an overview of why we’ll be using this technology stack. (If you’d rather get to the hands-on part straight away, jump to the project section.)
About Third-party Form-handling Services
There’s already a good number of API form-handling services that provides the features we need. These include:
The features they offer include:
email notification
spam blockage
integration with other services through Zapier
dashboard data view
file upload and storage
CSV export
That’s a lot of value that frees you from having to build such a service yourself. Also, it only takes about five minutes or less to integrate the service with an existing web application. Most platforms offer a free plan that gives you about 50 to 100 free submissions per month with about 100MB of file storage.
Paid plans start from $9 a month with 1,000 submissions and 1GB of file upload storage. If you’re using the service to capture leads, the price is quite fair. However, if you’re using it for a different purpose — such as collecting massive amounts field data — it can get expensive quickly.
This is where building your own form-handling service can be advantageous. There are several benefits, which include:
lower cost per form submission
implementation of custom security policies
unlimited integrations with other services
reduction in latency, since you have control of how and where the service is hosted
ability to add new features not currently offered by a form-handling provider
In regards to lower cost per submission, transaction email service providers such as SendGrid and Mailgun currently have an offer that allows you to send between 3,000 to 5,000 emails per month for free. The former’s offer is permanently free, while the latter’s offer only lasts for three months.
This, of course, is already too much email for anyone’s inbox. You’d probably want to send form data straight to your database or an application service designed to handle that data. If that’s the case, you’ll probably pay less than 10 dollars per a million submissions.
This pricing I’ve estimated is based on combined average pricing for major serverless computing and serverless database offerings. If you need file storage, you can get 250 Gigabytes of Linode Object Storage for $5 per month. You actually get so much more value when you spend the time to build the service yourself.
I hope those are enough reasons. If not, then learn to build just for the fun of it. You can apply the knowledge gained in other areas. In the next section, we’ll look into why we chose to build our own service with Cloudflare Workers.
About Cloudflare Workers
The first serverless computing platform to be introduced was Google App Engine, which was launched in 2008. However, the first commercially successful serverless offering was AWS Lambda, which was introduced by Amazon in 2014. Later, in 2016, Google introduced a second serverless offering known as Google Cloud Functions. IBM Cloud Functions and Azure Functions followed soon after.
While all these services provide the benefits of running back-end code at a significantly lower cost, most do suffer from a problem known as cold start. This is where an idle container hosting your function takes anywhere from 1 to 10+ seconds to respond to a request. There are many workarounds that have been documented to improve the situation, but not to solve it entirely.
Cloudflare Workers is the latest entry into the serverless computing market. The company has solved the cold start problem where idle serverless functions experience 0 millisecond boot time to respond to requests. They’ve achieved this by leveraging V8 runtime to execute serverless functions instead of running them in a Node.js environment. This guide explains more on how it works.
In addition, Cloudflare is an Edge computing platform. This basically means code is executed on servers nearest to end users. This greatly reduces network latency even further, and makes your application response instant.
Hopefully I’ve now convinced you that Cloudlflare Workers is the way to go. So let’s start building.
About the Project
The source code for the completed projects are included in the following links:
We’ll go through building the Workers application step by step in this tutorial. Then we’ll download and configure the completed SPA (linked above) to connect to our completed Workers project.
We won’t be building the UI. We’ll deploy the application and test it with the Workers application that we’re going to build. The following section describes all the prerequisites needed to follow along with the tutorial.
Prerequisites
This tutorial is intended for intermediate to advanced Node.js developers. I’ll assume you’re familiar with ES6+ notation and REST APIs. You’ll need the following setup in your development environment:
The REST Client extension is a more convenient tool for testing REST interfaces as opposed to using external applications.
Accounts Setup
In this section, we’ll set up all the service accounts we need to build our email-handling worker. Take note of all the API tokens and other IDs that we’ll use later on in the development process.
1. Custom Domain
In order to follow along this tutorial, it’s highly recommended that you have access to a custom domain and an email address using that domain. However, you can manage to get the code working using a sandbox domain and the free subdomain that Cloudflare gives you when you sign up. Do note that credit card information is required when setting up a custom domain on Mailgun.
Having a custom domain will allow you to:
deploy your Cloudflare projects on a custom domain
gain access to your deployed Workers logs in real time
send authentic emails that won’t end up in the spam box
If you don’t have access to a custom domain, I strongly suggest you purchase a new domain from FastComet. The reason I recommend them is because they’ll give you a free Lite Email package which you can use to set up your custom domain email address. Most providers will charge you extra for email hosting.
In the next section, we’ll set up a Mailgun account.
2. Mailgun Setup
Mailgun is an Email API service that allows developers integrate email functionality into their apps via APIs. We’ll use their REST API interface to send and email from our Workers application to a recipient. Basically this means we only need to use Fetch or Axios to send an email. Use the following guide to set up your Mailgun account:
Head over to the sign up page and create a new account using the free plan.
Verify your account using an email address and an SMS code sent to your phone.
On Mailgun’s dashboard, go to Sending > Domains and you’ll find a sandbox domain has been created for you. This is a free domain provided for you to test the sending of emails.
With a sandbox domain, you’re only allowed to send an email to an authorized recipient. On the current dashboard’s right sidebar, you’ll find a form where you can provide the email address of a recipient. Add one now. This will be the email address that will receive the emails sent from the Workers application that we’ll be building.
An email will be sent to the authorized recipient’s inbox. Click confirm to complete step 4.
On the sandbox’s Overview page, click on API > Select button.
Next, select the curl tab. Take note of your API Key and the API base URL.
Send a test email using the cURL command provided for the sandboxed domain. Ensure that you replace the relevant fields with your API tokens and your authorized email recipient.

Here’s a quick example of how you can send yours:
curl -s –user ‘api:key-0303d350c68aa534560ed0838bca66e’
https://api.mailgun.net/v3/sandbox9cfff108345efd4a15fd76.mailgun.org/messages
-F from=’John Doe
-F [email protected]
-F subject=”Hello”
-F text=”Message sent using Mailgun service”

If successful, you should receive output like that shown below:
{
“id”: “<[email protected]mailgun.org>“,
“message”: “Queued. Thank you.”
}

You should also receive an email either on your authorized recipient’s inbox or spam box. If this happens, you’ve successfully set up your Mailgun account.
If you’d like to use a custom domain as your sending domain, do note that credit card information is required. You can follow the instructions here to learn how to set that one up. Using a custom domain allows you to unlock sending limits, and also to have your email source validated such that they’ll always end up on users’ inbox and not the spam box.
At the end of this section, you should have access to the following:
an API KEY: for example, api:key-0303d350c68aa534560ed0838bca66e
an API BASE URL: for example, https://api.mailgun.net/v3/sandbox9cfff108345efd4a15fd76.mailgun.org
a FROM_EMAIL_ADDRESS: use any Gmail address or a custom domain address that you ‘ve registered with Mailgun
a TO_EMAIL_ADDRESS: an authorized recipient
Do note that the API key is also found under Settings > API Keys > Private API key.

To get started, simply sign up for a Cloudflare Workers account. Follow the instructions provided:
enter email address and password
choose a subdomain for your account
choose a plan: select free
verify your email address
Next, install and configure Wrangler CLI, which you’ll use to develop Workers projects:

npm install -g @cloudflare/wrangler

wrangler –version

wrangler login

wrangler whoami

In case the login command fails for you, there are a few workarounds which have been documented on this GitHub issue. These are the steps that worked for my machine:

Execute wrangler login again in the terminal.

As soon as the Authorize page loads, Press F12 to open the Inspector, then switch it to Network tab.

Click on the Authorize Wrangler button and wait till says “Wrangler is now authorized”.

Under the Network tab within the Inspector console, locate the last POST request. Click on it to highlight it.

A Request tab should appear. Click on it to access it. There should be some JSON data. The property “key” is the API token. Copy it.

Go back to the terminal and use ctrl + c to cancel the last command. Execute the command wrangler config. You’ll be asked to enter your API token. Paste the key you just copied, then press enter. It should return a “Successfully configured” message.

Confirm authentication was successful by executing wrangler whoami.

In the next subsection, we’ll look at how to add a custom domain to your Cloudflare account. If you don’t have one, simply skip to the “Project Development” section, where we can continue without one.
Custom Domain Setup on Cloudflare
If you have a custom domain, you’ll be able to access real-time logs of your Workers application. To set it up, simply follow thies instructions:

Add your website (custom domain) to Cloudflare: instructions here

Change your domain nameservers to Cloudflare: instructions here.
Adding your custom domain in Cloudflare will also enable you to publish your Workers application to a custom domain. We’ll see how to do this in a later section. Take note that changing domain servers takes effect within a minute, though you’ll be informed it takes 24 hours. You can confirm the status by using the global DNS checker.

Download the Cloudflared binary : download links here. Extract the binary and place it in your $PATH environment variable.

Authenticate Cloudflared command: instructions here for using cloudflared tunnel login command.

Once you’ve completed the above setup, you’ll be able to run the command wrangler tail to stream your published Workers application logs in real time.
Project Development
In this section, we’ll do the actual actual coding. You should have the following tokens and ids:
MAILGUN API KEY
MAILGUN API BASE URL
FROM EMAIL ADDRESS
TO EMAIL ADDRESS
Cloudflare account ID
Cloudflare zone ID (available under your custom domain dashboard in Cloudflare)
1. Generate Project
In this step, we’ll generate our Workers project. Simply execute the following commands in a terminal:

wrangler generate cloudflare-form-service

cd cloudflare-form-service
npm install

code .

Next, update wrangler.toml and provide your account_id:
name = “cloudflare-form-service”
type = “javascript”
account_id = “
workers_dev = true
route = “”
zone_id = “”

After saving your changes, open package.json, and overwrite the scripts section the following:
{
“scripts”: {
“dev”: “wrangler dev”,
“preview”: “wrangler preview”,
“format”: “prettier –write “**/*.{js,css,json,md}””
},
}

It’s handy having these commands set here so that you can easily launch them in VS Code. You can launch the dev command or simply execute npm run dev in your terminal. This should start the dev server, which should take a few seconds.
Create the file test.http and insert the following commands:
# Test GET request
GET http://localhost:8787/ HTTP/1.1

###

After saving, there should be a clickable “Send Request” link that appears in test.http file, right above the GET command. This feature is powered by the REST Client extension. Click on it to run the request. A new tab should open displaying the response. Take note of the roundtrip time displayed on the tab title.

In the next step, we’ll start writing code for handling POST requests.
2. Handling POST Requests
Let’s take a look at our current Workers code. Open index.js:
addEventListener(‘fetch’, event => {
event.respondWith(handleRequest(event.request))
})

async function handleRequest(request) {
return new Response(‘Hello worker!’, {
headers: { ‘content-type’: ‘text/plain’ },
})
}

Currently, our Workers application is listening for any Request type and passing it to the Response handler, which returns the text message “Hello worker!”
We’ll make the following changes:
define a specific response handler for POST requests
define a function for converting form data into a JavaScript object
block all other request types by returning a 404 message
Overwrite the current index.js with the following changes:
addEventListener(‘fetch’, event => {
event.respondWith(handleRequest(event.request))
})

async function handleRequest(request) {
if (request.method === ‘POST’) {
return handlePostRequest(request)
} else {
return new Response(‘Object Not Found’, {
statusText: ‘Object Not Found’,
status: 404,
})
}
}

async function readRequestBody(request) {
const { headers } = request
const contentType = headers.get(‘content-type’)
if (!contentType) {
throw ‘Content type has not been set!’
}
if (contentType.includes(‘application/json’)) {
const body = await request.json()
return body
} else if (contentType.includes(‘form’)) {
const formData = await request.formData()
let body = {}
for (let entry of formData.entries()) {
body[entry[0]] = entry[1]
}
return JSON.stringify(body)
} else {
throw ‘Content type not recognized!’
}
}

async function handlePostRequest(request) {
let json

try {
json = await readRequestBody(request)
} catch (error) {
return new Response(error, {
headers: { ‘content-type’: ‘text/plain’ },
statusText: error,
status: 500,
})
}

return new Response(JSON.stringify(json), {
headers: { ‘content-type’: ‘text/json’ },
status: 400,
})
}

Next, append the following HTTP commands in test.http:
# Test invalid POST with no content type
POST http://localhost:8787/ HTTP/1.1

###

# Test valid POST request
POST http://localhost:8787/ HTTP/1.1
application/json

{
“firstName”: “John”,
“lastName”: “Doe”,
“email”: “[email protected]”,
“message”: “Such a great show. Keep it up!”,
“subscribe”: false
}

###

Make sure to use ### to separate each HTTP command. Start the dev server using wrangler dev or npm run dev command. Run each URL. You should expect the following results:
GET request: returns 404 error message
POST request with no content type: returns 400 error message about content type
Valid POST request: simply returns the POST JSON data we submitted

Currently, we’re not performing any validation on the JSON data that comes with POST request. Let’s fix that in the next step.
3. Schema Validation
In order to validate data in JSON formats, we’ll use JSON Schema, an open standard that’s used to define the structure of your data. Schema definitions are run against data using validation tools to check if the structure is compliant. If not, a list of validation errors is returned. You can learn more about the basics of JSON Schema here.
We’ll start by installing @cfworker/json-schema, a JSON Schema validator that can run in the Workers environment. As mentioned earlier, serverless execution environments generally lack some APIs required to support a full Node.js environment. So the team at Cloudflare Workers built one that can run on their platform. It’s based on ajv, a JSON validator for Node.js.
Execute the following command to install the package:
npm install @cfworker/json-schema

Since we need to use the import statement, we need to change our Workers build type from “JavaScript” to “webpack”. This is done in wrangler.toml:

type = “webpack”

Next, let’s create a script named validator.js that will contain our schema definition and validation logic. Insert the following code:
import { Validator } from ‘@cfworker/json-schema’

const validator = new Validator(
{
type: ‘object’,
required: [‘firstName’, ‘lastName’, ’email’, ‘message’, ‘subscribe’],
properties: {
firstName: { type: ‘string’ },
lastName: { type: ‘string’ },
email: { type: ‘string’, format: ’email’ },
message: { type: ‘string’ },
subscribe: { type: ‘boolean’ },
},
},
‘2019-09’,
false,
)

function validate(input) {
const { valid, errors } = validator.validate(input)

const errs = errors.map(error => ({
type: error.keyword,
message: error.error,
}))

return {
valid,
errors: errs,
}
}

export default validate

Next, we’ll import and make use of the validate function in our handlePostRequest function. Open index.js and update accordingly:
import validate from ‘./validator’

async function handlePostRequest(request) {
let json

try {
json = await readRequestBody(request)
} catch (error) {
return new Response(error, {
headers: {
‘content-type’: ‘text/plain’,
},
statusText: error,
status: 500,
})
}

const results = validate(json)

if (!results.valid) {
return new Response(JSON.stringify(results), {
headers: {
‘content-type’: ‘text/json’,
},
status: 400,
})
}

return new Response(JSON.stringify(json), {
headers: {
‘content-type’: ‘text/json’,
},
status: 200,
})
}

To test this new functionality, we’ll add a couple more HTTP commands. Simply add this to test.http file:
# Test invalid POST request – check missing data inputs
POST http://localhost:8787/ HTTP/1.1
application/json

{
“firstName”: “John”
}

###

# Test invalid POST request – check invalid types
POST http://localhost:8787/ HTTP/1.1
application/json

{
“firstName”: “John”,
“lastName”: “Doe”,
“email”: “john.doe”,
“message”: “Such a great show. Keep it up!”,
“subscribe”: “false”
}

###

Finally, make sure wrangler dev server is running, then execute all the HTTP commands. Below is an example of an expected failing validation response:

For the valid POST request, this should perform as before — that is, return the request JSON data in its response. In the next section, we’ll integrate the email service Mailgun.
Email Integration
Building a Workers application that can send emails is quite easy. We don’t need to install any new package for this. We’ll simply use Mailgun’s REST API service. First, create the file email-service.js and insert the following code:
import htmlTemplate from ‘./email-html-template.js’
import textTemplate from ‘./email-text-template.js’

function urlEncodeObject(obj) {
return Object.keys(obj)
.map(k => encodeURIComponent(k) + ‘=’ + encodeURIComponent(obj[k]))
.join(‘&’)
}

function sendMail(json) {
const data = {
to: TO_EMAIL_ADDRESS,
from: FROM_EMAIL_ADDRESS,
subject: ‘New Contact: Online Guest Book’,
text: textTemplate(json),
html: htmlTemplate(json),
}

const dataUrlEncoded = urlEncodeObject(data)
const opts = {
method: ‘POST’,
headers: {
Authorization: ‘Basic ‘ + btoa(‘api:’ + MAILGUN_API_KEY),
‘Content-Type’: ‘application/x-www-form-urlencoded’,
‘Content-Length’: dataUrlEncoded.length.toString(),
},
body: dataUrlEncoded,
}

return fetch(`${MAILGUN_API_BASE_URL}/messages`, opts)
}

export default sendMail

The sendMail function first collects all the information needed to construct an email. Using URL encoding, the information is encoded into an URL format that can be sent over the Internet. If you look at the information collected, you may have noticed that we’re accessing a number of constant variables that we haven’t declared. These are environment variables that get injected by Cloudflare when we run our script. There are two ways of declaring them:
Using wrangler secret put command. Running this will upload the environment variable straight to your Workers application’s settings. It will also automatically encrypt the value.
The second option is to first publish your application using the wrangler publish command. Next, on dash.cloudflare.com, navigate to Dashboard > Workers > Click on “cloudflare-form-service” > Settings > Environment Variables. This where you can key in all the required variables needed for the email-service script to run. You can leave the values plain if you’d like to edit them later, or click the encrypt button to secure the tokens.

In the example above, I’ve left mine unencrypted so that I can change later. However, it’s highly recommended you use the wrangler CLI to set up your environment variables. Do note this will get reset later once we start defining our staging and production environments.
Next, we need to create HTML and text templates. These are required to format our email to make the data presentable.
Create the file email-text-template.js and insert the following code:
const template = data => {
return `
Online Guest Book Contact
————————–
First Name : ${data.firstName}
Last Name : ${data.lastName}
Email : ${data.email}
Message : ${data.message}
Subscribed : ${data.subscribed ? ‘Yes’ : ‘No’}
`
}

export default template

Create the file email-html-template.js and insert the following code:
const template = data => {
return `






Email Template


Online Guest Book Contact

First Name
${data.firstName}

Last Name
${data.lastName}

Email
${data.email}

Message
${data.message}

Subscribed
${data.subscribed ? ‘Yes’ : ‘No’}



`
}

export default template

Finally, update index.js as follows:

import sendMail from ‘./email-service’

async function handlePostRequest(request){

try {
const result = await sendMail(json)
if (result.status == 200) {
return new Response(
JSON.stringify({ message: ‘Message succesfully sent’ }),
{
headers: { ‘content-type’: ‘text/json’ },
},
)
} else {
return new Response(
JSON.stringify({ message: ‘Message submission failed!’, result }),
{
headers: { ‘content-type’: ‘text/json’ },
status: 400,
},
)
}
} catch (error) {
return new Response(error, {
headers: { ‘content-type’: ‘text/plain’ },
statusText: ‘An error occurred’,
status: 500,
})
}
}

Here’s a link for the complete index.js file if you’re unsure where to place this new code block. The new code block is simply passing data from request.json to the sendMail function, then waiting for a response. If it’s a success, a success message is sent. Otherwise, an error message is sent back. The catch block is for sending any other error message that we may not anticipate.
Launch wrangler dev server and re-execute all the HTTP commands in test.http. Everything should work like before except the “Test valid POST request” test. When executed, you should get the following JSON response:
{
“message”: “Message succesfully sent”
}

You should be receiving an email almost instantly. Check your inbox for something like this:

If you’re using a sandbox for your sending domain, the email will likely head straight to your spam folder. Go there, locate it and confirm that you’ve received your email. In the next section, we’ll look at how to add CORS headers to our API responses.

CORS (cross-origin resource sharing) is an API security feature implemented in browsers that ensures web applications have the right permissions to access information from a server. So far, we’ve only been using non-browser tools to perform Worker API requests without any issues. Also, performing an API request between one server and another doesn’t bring up any CORS-related issue. However, once we deploy our React application and try querying our Workers’ API using a browser request, we’ll be met with CORS errors.
To fix this, we need to do open index.js in our Workers application and add the following right after the import statements:
const corsHeaders = {
‘Access-Control-Allow-Origin’: ‘*’,
‘Access-Control-Allow-Headers’: ‘Content-Type’,
‘Access-Control-Allow-Methods’: ‘POST’,
‘Access-Control-Max-Age’: ‘86400’,
}

Next, we need to handle CORS preflight requests, which is a mechanism that browsers use to check the CORS protocols and the specific methods and headers that our server supports. This type of request is done using the OPTIONS method. Update the handleRequest function as follows:
async function handleRequest(request) {
if (request.method === ‘POST’) {
return handlePostRequest(request)
} else if (request.method === ‘OPTIONS’) {
return new Response(‘OK’, { headers: corsHeaders })
} else {
return new Response(‘Object Not Found’, {
statusText: ‘Object Not Found’,
status: 404,
})
}
}

Finally, for each response returned in the code, append or add the CORS headers, …corsHeaders, like so:
return new Response(‘OK’, { headers: corsHeaders })

return new Response(
JSON.stringify({ message: ‘Message succesfully sent’ }),
{
headers: { ‘content-type’: ‘text/json’, …corsHeaders },
},
)

Make sure each returned response has the corsHeaders. Otherwise, you’ll encounter CORS errors when testing the Form User Interface. See the complete index.js for clarification. Once you finish, your Workers application will be CORS ready and should work with any web browser without any issue.
In the next section, we’ll look at deploying our Workers application.
Project Deployment
In this section, we’ll look into how to deploy our Workers application. We’ll first start with using Workers’ free subdomain, then later use a custom domain. We’ll also set up staging and production environments.
Deploy Form Handling Workers Service
Deploying your Workers application to Cloudflare servers is quite simple. All you have to do is execute this command:
wrangler publish

Next, append the following HTTP commands in test.http:
###

#———————–#
# |
# PUBLISHED HTTP TESTS |
# |
#———————–#

# Test GET request
GET cloudflare-form-service..workers.dev/ HTTP/1.1

###

# Test invalid POST request – check missing data inputs
POST cloudflare-form-service..workers.dev/ HTTP/1.1
application/json

{
“firstName”: “John”
}

###

# Test valid POST request on published URL
POST cloudflare-form-service..workers.dev/ HTTP/1.1
Content-Type: application/json

{
“firstName”: “John”,
“lastName”: “Doe”,
“email”: “[email protected]”,
“message”: “Such a great show. Keep it up!”,
“subscribe”: false
}

Make sure to replace the term with the subdomain name you used to register your Cloudlflare Workers account. After saving, run each of the new requests to ensure you receive the expected responses. If you have a good internet connection, each published request should complete in under a second. However, the “valid post request” test should take slightly longer than second, since there’s a small delay caused by the email API request occurring within the handlePostRequest function.
IMPORTANT: if you don’t have a custom domain, simply skip to the “Deploy Form User Interface” section and follow along from there.
Currently, our Workers application is running on Cloudflare’s workers.dev domain. If you’d like to publish this on your custom domain, we’ll need to set up a couple of environments first. Actually, it’s not necessary to do this, but it’s good practice having separate environments for testing and production.
With Worker Environments, your application will be deployed to multiple places using the same code but with different environment variables. The environments we’ll set up will be called staging and production. Each will have its own unique URL, which can be accessed as follows:
production: https://cloudflare-form-service..workers.dev
staging: https://cloudflare-form-service-staging..workers.dev
Update your wrangler.toml as follows:
name = “cloudflare-form-service-dev”
type = “webpack”
account_id = “

[env.staging]
name = “cloudflare-form-service-staging”
workers_dev = true

[env.production]
name = “cloudflare-form-service”
workers_dev = false
route = “https://contact-form-worker.example.com/”
zone_id = “

Replace all the IDs with your tokens and example.com with your custom domain. You may notice that we’ve specified a subdomain in route that actually doesn’t exist. We’ll set that up right now. Simply go to your main Cloudflare dashboard, then click on the DOMAIN you added. Click the DNS tab, then create a new record as follows:
Type: CNAME
Name: contact-form-worker
Target: @
See an example below.

After clicking the Save button, you’ll need to publish your production environment using the following command:
wrangler publish -e production

Using the route defined in wrangler.toml, our production environment URL — cloudflare-form-service..workers.dev — will be mapped to contact-form-worker.example.com. Since we just published our application to a new environment, you’ll have to re-upload your environment application keys again using the following commands:
wrangler secret put TO_EMAIL_ADDRESS –env production
wrangler secret put FROM_EMAIL_ADDRESS –env production
wrangler secret put MAILGUN_API_KEY –env production
wrangler secret put MAILGUN_API_BASE_URL –env production

Finally, add the following HTTP commands to test your application at your custom domain:
###

# Test GET request
GET contact-form-worker.example.com/ HTTP/1.1

###

# Test invalid POST request – check missing data inputs
POST contact-form-worker.example.com/ HTTP/1.1
application/json

{
“firstName”: “John”
}

###

# Test valid POST request on published URL
POST contact-form-worker.example.com/ HTTP/1.1
Content-Type: application/json

{
“firstName”: “John”,
“lastName”: “Doe”,
“email”: “[email protected]”,
“message”: “Such a great show. Keep it up!”,
“subscribe”: false
}

Replace all example.com with your actual custom domain. Run all the new tests and ensure that they all return the expected responses. In the next section, we’ll supply you with front-end code you can use to test your production Workers application.
Deploy Form User Interface
We can’t complete our Workers form handling server without testing it with a real application. I’ve built out a Cloudflare Form UI you can use to test your Workers service. In order to run it locally, you need first to install dependencies, then create an .env file and place the URL of your Workers application:
VITE_FORM_ENDPOINT_URL=

Next, you run your application locally using the npm run dev command. Alternatively, you can deploy it to a platform such as:
The build settings are:
Build command: npm run build
Build folder: dist
Ensure that you upload the required environment variable VITE_FORM_ENDPOINT_URL as well. Below is a screenshot of the Form User Interface deployed on Cloudflare Pages.

In case you encounter a fail message, make sure that:
all your Workers responses have the CORS headers
you’ve executed wrangler publish on your Workers application project
environment variables have been set
Summary
I hope you’ve learned how to build and deploy your own form-handling service with email notifications using serverless functions. The time spent working on this can help you save tremendously on all your form processing needs. There are many more serverless features we haven’t looked into, such as:
The latter two services allow execution of serverless functions for much longer than ten milliseconds. There’s actually no time limit provided you don’t exceed limits that would interfere with other services. While Cloudflare Workers may not be the ideal platform for hosting traditional back-end code, they do present many opportunities for building back-end solutions that aren’t easy or possible to do with monolithic platforms.

Coded at

Share your love

173 Comments

  1. The power from the Internet will assist you in order to someone that will fit your requirement.
    SEO usually takes some time, because serps take quite some time to rank
    you.

  2. Hi! I know this is kinda off topic however , I’d figured I’d ask.

    Would you be interested in trading links or maybe guest writing a blog post or
    vice-versa? My blog goes over a lot of the same topics as yours and I think we
    could greatly benefit from each other. If you happen to be interested
    feel free to shoot me an email. I look forward to hearing from you!
    Wonderful blog by the way!

  3. You made ѕome really good points there.
    Ι chеcked on the net tо learn more about
    the issue ɑnd found moѕt individuals will go along with
    yoᥙr vieᴡs on this website.

  4. Simply wish to say your article is as astonishing.

    The clarity in your post is just great and i can assume you’re an expert on this subject.
    Fine with your permission let me to grab your RSS feed to
    keep updated with forthcoming post. Thanks a million and please
    continue the enjoyable work.

  5. Every weekend i used to visit this web site, because i want enjoyment, as
    this this web site conations in fact good funny data too.

  6. Hey! Someone in my Facebook group shared this site with us so I came to check
    it out. I’m definitely loving the information.
    I’m bookmarking and will be tweeting this to my followers!
    Fantastic blog and outstanding style and design.

  7. It’s in fact very complex in this full of activity
    life to listen news on TV, therefore I only use the web for that purpose, and get the
    latest news.

  8. El reloj digital de CASIO no es sólo un reloj moderno, sino
    a su vez un complementario elegante para cualquier bicoca
    en la que quiera realzar su estilo.

  9. great issues altogether, you simply received a emblem
    new reader. What might you suggest in regards to your publish that you just made some days in the past?
    Any sure?

  10. Thanks on your marvelous posting! I quite enjoyed reading it, you will be a great author.
    I will remember to bookmark your blog and will eventually come back down the road.
    I want to encourage one to continue your great posts,
    have a nice day!

  11. I’m not that much of a online reader to be honest but
    your sites really nice, keep it up! I’ll go ahead and bookmark your website to come back in the future.
    Cheers

  12. Hello there I am so grateful I found your weblog, I really found you by error, while
    I was searching on Aol for something else, Nonetheless I am here now and
    would just like to say thanks a lot for a tremendous
    post and a all round interesting blog (I also love
    the theme/design), I don’t have time to read it all at the
    minute but I have saved it and also included your RSS feeds, so when I have
    time I will be back to read more, Please do keep up the superb work.

  13. Undeniably consider that which you stated. Your favourite
    justification seemed to be on the web the simplest factor
    to be mindful of. I say to you, I certainly
    get annoyed while other folks think about issues
    that they just don’t recognize about. You controlled to hit the nail upon the top
    as neatly as outlined out the entire thing without having
    side-effects , people could take a signal.

    Will likely be again to get more. Thanks

  14. Thank you for the auspicious writeup. It in reality was once a entertainment account it.
    Glance complicated to more added agreeable from you! However, how could we communicate?

  15. Hi there everyone, it’s my first pay a quick
    visit at this site, and paragraph is genuinely
    fruitful in favor of me, keep up posting these types of articles.

  16. I got this site from my friend who shared with me on the topic of
    this website and now this time I am browsing this site and reading very informative content at this place.

  17. I love your blog.. very nice colors & theme. Did you make this website
    yourself or did you hire someone to do it for you?
    Plz respond as I’m looking to construct my own blog and would like to find out where u got this from.
    thank you

  18. Greetings! Very helpful advice in this particular article!
    It is the little changes that will make the greatest changes.

    Thanks for sharing!

  19. Does your blog have a contact page? I’m having trouble locating it but, I’d like
    to shoot you an email. I’ve got some recommendations for your blog you might be
    interested in hearing. Either way, great website and I look forward to
    seeing it develop over time.

  20. Hmm it seems like your site ate my first comment (it was extremely
    long) so I guess I’ll just sum it up what I wrote and say, I’m thoroughly enjoying your
    blog. I too am an aspiring blog blogger but I’m still new to
    everything. Do you have any suggestions for rookie blog writers?
    I’d definitely appreciate it.

  21. Excellent beat ! I wish to apprentice while you amend your site,
    how can i subscribe for a blog web site? The account aided me a acceptable deal.
    I had been tiny bit acquainted of this your broadcast offered bright clear concept

  22. I am really loving the theme/design of your weblog.
    Do you ever run into any internet browser compatibility
    issues? A couple of my blog audience have complained
    about my website not working correctly in Explorer
    but looks great in Opera. Do you have any suggestions
    to help fix this problem?

  23. Hello, i think that i saw you visited my website thus i came to “return the
    favor”.I am attempting to find things to enhance my website!I suppose its ok to use a few
    of your ideas!!

  24. I’m really inspired together with your writing talents as smartly
    as with the layout on your blog. Is that this a paid subject or did you
    customize it your self? Anyway keep up the excellent high quality writing, it’s rare
    to see a great weblog like this one these days..

  25. Hello there, I believe your web site may be having internet browser compatibility problems.
    Whenever I look at your blog in Safari, it looks
    fine however, if opening in I.E., it has
    some overlapping issues. I just wanted to provide you with a
    quick heads up! Aside from that, wonderful website!

  26. I know this if off topic but I’m looking into starting
    my own weblog and was wondering what all is required to get set up?
    I’m assuming having a blog like yours would cost a pretty penny?
    I’m not very web savvy so I’m not 100% certain. Any suggestions or advice would be greatly
    appreciated. Many thanks

  27. These are really enormous ideas in on the topic of blogging.
    You have touched some good things here. Any way keep up wrinting.

  28. This is really interesting, You are a very skilled blogger.

    I have joined your rss feed and look forward to seeking
    more of your excellent post. Also, I’ve shared your site in my social networks!

  29. Hello there! Do you use Twitter? I’d like to follow you if that would be ok.
    I’m undoubtedly enjoying your blog and look forward
    to new updates.

  30. Hi there, just became alert to your blog through Google,
    and found that it is really informative. I’m gonna watch
    out for brussels. I will appreciate if you continue this in future.
    A lot of people will be benefited from your writing.
    Cheers!

  31. Excellent website. Lots of helpful information here.
    I’m sending it to some pals ans additionally sharing in delicious.
    And obviously, thank you on your sweat!

  32. Unquestionably believe that which you stated. Your favorite justification appeared to be on the net the simplest thing
    to be aware of. I say to you, I definitely get annoyed while people
    think about worries that they plainly do not know about.
    You managed to hit the nail upon the top and defined out the whole thing without having side effect , people can take a signal.
    Will likely be back to get more. Thanks

  33. I got this web site from my pal who told me concerning
    this web page and now this time I am visiting this web
    page and reading very informative posts here.

  34. Undeniably believe that which you said. Your favorite reason seemed to
    be on the net the easiest thing to be aware of. I say to you, I certainly
    get irked while people consider worries that they just do not know about.
    You managed to hit the nail upon the top and
    also defined out the whole thing without having side-effects , people could take a signal.

    Will likely be back to get more. Thanks

  35. When I originally commented I clicked the “Notify me when new comments are added” checkbox and now each time a comment is added I get four emails with the same comment.
    Is there any way you can remove me from that service?
    Many thanks!

  36. My brother recommended I might like this website. He was entirely right.
    This post truly made my day. You cann’t imagine just how much time I had spent for this information!
    Thanks!

  37. What’s up i am kavin, its my first occasion to commenting anywhere, when i read this piece
    of writing i thought i could also create comment due to this good
    article.

  38. I like the valuable info you provide for your articles.
    I’ll bookmark your weblog and test again right here regularly.
    I am slightly sure I will learn plenty of new stuff right right here!
    Good luck for the following!

  39. I know this if off topic but I’m looking into starting my
    own blog and was wondering what all is required to get set up?

    I’m assuming having a blog like yours would cost a pretty penny?
    I’m not very web savvy so I’m not 100% certain.
    Any recommendations or advice would be greatly
    appreciated. Many thanks

  40. Wow, awesome blog format! How long have you ever been running a blog for?
    you made running a blog look easy. The entire look of your site is
    excellent, let alone the content material!

  41. Aw, this was a very nice post. Spending some time and actual effort
    to make a superb article… but what can I say… I hesitate a whole
    lot and don’t seem to get nearly anything done.

  42. I have learn several just right stuff here. Definitely worth bookmarking for
    revisiting. I surprise how so much effort you set
    to make this type of magnificent informative website.

  43. Awesome blog you have here but I was wondering if you knew of any community forums that cover the
    same topics talked about in this article? I’d really like to be a part of online community where I can get suggestions
    from other knowledgeable individuals that share the same interest.
    If you have any suggestions, please let me know. Thanks a lot!

  44. Fantastic beat ! I would like to apprentice
    even as you amend your website, how can i subscribe for a
    weblog website? The account helped me a applicable deal.
    I have been tiny bit acquainted of this your broadcast
    offered shiny clear idea

  45. Thanks a bunch for sharing this with all of us you
    actually know what you are talking about! Bookmarked. Kindly additionally consult with my
    web site =). We can have a link change contract among us

  46. I don’t know whether it’s just me or if everybody else experiencing issues with
    your blog. It appears like some of the written text on your content are running off the screen. Can somebody else please provide feedback and let me know if this is happening
    to them as well? This may be a problem with my
    web browser because I’ve had this happen previously.

    Kudos

  47. If you are going for most excellent contents like I do, simply
    visit this website everyday as it offers quality contents, thanks

  48. My relatives every time say that I am killing my time here
    at net, however I know I am getting familiarity everyday by reading thes pleasant
    articles.

  49. I do not even know how I ended up here, but I thought this post was good. I don’t know who you are but certainly you’re going to a famous blogger if you aren’t already 😉 Cheers!

  50. I visit each day a few sites and blogs to read content, but this blog offers quality based writing. I like the valuable information you provide in your articles. I’ll bookmark your weblog and check again here frequently. I’m quite certain I will learn lots of new stuff right here! Best of luck for the next!

  51. I have read so many posts on the topic of the blogger lovers however this post is really a pleasant piece of writing, keep it up.

  52. When I initially commented I clicked the “Notify me when new comments are added” checkbox and
    now each time a comment is added I get three e-mails
    with the same comment. Is there any way you can remove people from that service?
    Thank you!

  53. I visit each day a few sites and blogs to read content, but this blog offers quality based writing. I like the valuable information you provide in your articles. I’ll bookmark your weblog and check again here frequently. I’m quite certain I will learn lots of new stuff right here! Best of luck for the next!

  54. I visit each day a few sites and blogs to read content, but this blog offers quality based writing. I like the valuable information you provide in your articles. I’ll bookmark your weblog and check again here frequently. I’m quite certain I will learn lots of new stuff right here! Best of luck for the next!

  55. Hey there just wanted to give you a quick heads up and let you
    know a few of the pictures aren’t loading correctly. I’m not sure why
    but I think its a linking issue. I’ve tried it in two different internet browsers and both show the same results.

  56. I visit each day a few sites and blogs to read content, but this blog offers quality based writing. I like the valuable information you provide in your articles. I’ll bookmark your weblog and check again here frequently. I’m quite certain I will learn lots of new stuff right here! Best of luck for the next!

  57. always i used to read smaller articles that as well clear their motive, and that is also
    happening with this article which I am reading here.

  58. I do not even know how I ended up here, but I thought this post was good. I don’t know who you are but certainly you’re going to a famous blogger if you aren’t already 😉 Cheers!

  59. Wow, awesome blog layout! How long have you been blogging for?
    you make blogging look easy. The overall look of your site
    is fantastic, let alone the content!

  60. Howdy! I could have sworn I’ve been to this blog before but after browsing through some of the post I realized it’s new to me. Nonetheless, I’m definitely delighted I found it and I’ll be book-marking and checking back frequently!

  61. I visit each day a few sites and blogs to read content, but this blog offers quality based writing. I like the valuable information you provide in your articles. I’ll bookmark your weblog and check again here frequently. I’m quite certain I will learn lots of new stuff right here! Best of luck for the next!

  62. Hi everyone, it’s my first pay a visit at this site, and article is truly
    fruitful in support of me, keep up posting these articles or reviews.

  63. This is really interesting, You’re an excessively
    skilled blogger. I’ve joined your rss feed and stay up for in quest of more of your fantastic post.
    Additionally, I have shared your web site
    in my social networks

  64. Great goods from you, man. I have understand your stuff previous to and you’re just too fantastic.
    I actually like what you’ve acquired here, certainly like what you’re stating and the
    way in which you say it. You make it enjoyable and you still care for
    to keep it smart. I can not wait to read far more from
    you. This is actually a great website.

  65. I loved as much as you’ll receive carried out right here. The sketch
    is attractive, your authored subject matter stylish.
    nonetheless, you command get bought an shakiness over that you
    wish be delivering the following. unwell unquestionably come further formerly again since exactly the same nearly
    a lot often inside case you shield this hike.

  66. Spot on with this write-up, I really feel this amazing site needs much more
    attention. I’ll probably be back again to
    read more, thanks for the advice!

  67. When someone writes an piece of writing he/she keeps the image of a
    user in his/her mind that how a user can know it.
    So that’s why this post is great. Thanks!

  68. each time i used to read smaller articles or reviews that also clear their motive, and that is also happening with
    this paragraph which I am reading here.

  69. I’ve been surfing online more than 4 hours today, yet
    I never found any interesting article like yours. It is pretty worth enough for me.
    Personally, if all webmasters and bloggers made good content as you did, the
    net will be much more useful than ever before.

  70. Hi, Neat post. There’s an issue along with your web site in internet explorer,
    could check this? IE nonetheless is the market leader and a
    good portion of other people will omit your magnificent writing because of this problem.

  71. I simply couldn’t leave your website prior to suggesting that I really enjoyed the usual information a person supply in your guests?
    Is gonna be again incessantly to check out new posts

  72. Every one of many segments that may affect the stock costs have simply been gotten over in the present circumstance.
    Horowitz said that individually, the well being ministry would
    plug a Pfizer supply gap for ongoing two-dose inoculations of the final adult inhabitants by utilizing Moderna Inc (MRNA.O) vaccines already in stock.
    Subject testing this I went for a cycle using the bike mount this has can rotate the aspect to aspect view
    via a click on mechanism a strong match though I might want a touch extra tightness
    on the fully rotatable head. Our rigorous information validation course of yields an error fee of lower
    than .001% every year, offering site guests quality data they
    will trust. The main goal of such comfortable wares is
    to create a scenario through which you’ll have an efficient data storage system that will provide help to
    retailer all data for future use. As seen by knowledge from SurveyMonkey,
    Snapchat noticed 54.5 million downloads between January and July this year.

    Lastly, you might be interested to know that Snapchat is more standard than most apps
    available on the market at this time. In an honest carmated day buying and selling system,
    a product program or robot may be utilized to
    play out the trades as for some monetary specialist.

  73. I think that everything posted was very logical. However, what about this?
    suppose you added a little content? I am not saying your content is not solid., but suppose you added
    a headline to maybe grab a person’s attention? I
    mean Form Handling for Jamstack Sites Using Cloudflare Workers – SitePoint – Coding Hindi is kinda vanilla.
    You could peek at Yahoo’s home page and see how they write news titles to grab viewers to open the links.
    You might add a related video or a picture or
    two to grab people excited about everything’ve written. In my opinion, it might bring
    your posts a little livelier.

  74. Apikasi Game Slot merupakan aplikasi yang dapat meretas semua permainan game
    slot online. Dengan tingkatan pasar permainan game slot yang
    begitu besar di Indonesia. Kru kami akan menolong kamu untuk mendapatkan aplikasi berasal dari
    permainan game slot ini.

    Fungsi dan faedah berasal dari aplikasi ini adalah sebuah generator game slot.
    Dimana ini adalah aplikasi yang sanggup menopang kamu memilih
    permainan apa yang wajib dan perlu dimainkan sesuai bersama ketentuan yang telah
    kami kalkulasi dari sistem program yang dipasang di setiap permainan game slot yang ada.
    Ini dapat mempermudah anda memenangkan seluruh permainan yang ada.

    Semua permainan yang tersedia di dalam aplikasi telah kami
    uji coba ketepatannya. Sehingga kamu cukup generate permainan yang ada di dalam aplikasi yang sudah
    kami rancang. Kalian tinggal ikuti permainan apa yang
    kalian idamkan lalu aplikasi kami dapat membantu anda sebabkan proses yang akan menolong
    kamu memenangkan permainan slot tersebut.

  75. Nice post. I used to be checking continuously this blog
    and I’m inspired! Very useful information particularly the closing phase 🙂 I care for such information much.
    I was looking for this particular info for a long time.
    Thank you and good luck.

  76. Wonderful blog! I found it while surfing around on Yahoo News.

    Do you have any tips on how to get listed in Yahoo News?

    I’ve been trying for a while but I never seem to get there!

    Thank you

  77. Greetings! Very helpful advice within this post!
    It is the little changes that make the largest changes.
    Thanks a lot for sharing!

  78. It’s amazing to visit this site and reading the views of all friends on the
    topic of this post, while I am also eager of getting knowledge.

  79. เว็บไชต์พนันออนไลน์ มาตราฐานสูงสุด UFABET ตั้งใจปรับปรุงทุกต้นแบบ เพื่อความพึงพอใจสูงสุดของสมาชิก เว็บไซต์พนันบอลออนไลน์ ที่เปิดราคาบอลยอดเยี่ยม ยูฟ่าเบท มอบข้อแนะนำดีที่สุด ให้กับสมาชิก เว็บพนันบอล แจกเครดิตพนันบอลฟรี ทุกๆวัน แล้วก็เกื้อหนุน เซียนบอล มาให้ สูตรพนันบอล วิเคราะห์ วิภาควิจารณ์ กันทุกวี่วัน ลงทะเบียนกับ เว็บไซต์พนันบอลออนไลน์ วันนี้รับสิทธิพิเศษโดยทันที

  80. Hi, Neat post. There’s an issue with your site in internet explorer, might check this?
    IE nonetheless is the marketplace leader and a big component to folks
    will pass over your excellent writing because of this problem.

  81. My partner and I stumbled over here coming from a
    different page and thought I might as wel check things out.
    I like what I see so now i’m following you. Look forward to
    looking at your web page for a second time.

  82. naturally like your website but you have to check the spelling on several of your
    posts. A number of them are rife with spelling problems and I
    in finding it very troublesome to inform the truth on the other hand I will definitely
    come again again.

  83. Great web site. Plenty of useful information here. I’m sending it to several friends ans also sharing in delicious.
    And naturally, thanks to your effort!

  84. Howdy! I just want to offer you a huge thumbs up for your great info you have here
    on this post. I’ll be returning to your web site for
    more soon.

  85. Howdy! This post couldn’t be written any better! Reading this post reminds me of
    my old room mate! He always kept talking about this. I will forward this write-up
    to him. Pretty sure he will have a good read. Thank
    you for sharing!

  86. I like the helpful info you provide in your articles.
    I will bookmark your weblog and check again here regularly.
    I’m quite sure I will learn a lot of new stuff right here!
    Good luck for the next!

  87. I wanted to thank you for this fantastic read!! I definitely loved every little bit
    of it. I have you book-marked to check out new things you post…

  88. Pretty nice post. I just stumbled upon your weblog
    and wished to mention that I have truly loved surfing around your weblog posts.
    In any case I’ll be subscribing for your feed and I
    hope you write again very soon!

  89. Magnificent items from you, man. I’ve have in mind your stuff prior to and
    you’re simply too fantastic. I really like what
    you have obtained right here, really like what you’re stating and the way wherein you
    assert it. You make it enjoyable and you continue to care
    for to stay it smart. I can not wait to read far more from you.
    This is actually a great web site.

  90. I every time used to read article in news papers but now as
    I am a user of web therefore from now I am using net for articles or reviews,
    thanks to web.

  91. Hello there! This is my first visit to your blog!
    We are a collection of volunteers and starting a new initiative in a
    community in the same niche. Your blog provided us valuable
    information to work on. You have done a wonderful job!

  92. Howdy! Do you know if they make any plugins to assist
    with Search Engine Optimization? I’m trying
    to get my blog to rank for some targeted keywords but I’m not seeing very
    good success. If you know of any please share.
    Thank you!

  93. Thanks for the auspicious writeup. It actually was a leisure
    account it. Look complicated to far introduced agreeable from you!

    By the way, how can we communicate?

  94. Greetings from Colorado! I’m bored to tears at work so I decided to check
    out your site on my iphone during lunch break. I enjoy the knowledge you present here and can’t wait to take a look
    when I get home. I’m amazed at how quick your blog loaded on my mobile ..
    I’m not even using WIFI, just 3G .. Anyways, awesome blog!

  95. Greetings from Florida! I’m bored at work so I decided to browse your site on my iphone during lunch break.
    I love the knowledge you present here and can’t wait to
    take a look when I get home. I’m shocked at how quick your blog loaded on my
    cell phone .. I’m not even using WIFI, just 3G .. Anyhow, good site!

  96. Hey! I just wanted to ask if you ever have any problems with hackers?
    My last blog (wordpress) was hacked and I ended up losing months of hard work due to no data backup.
    Do you have any methods to prevent hackers?

  97. Hey I know this is off topic but I was wondering if you knew of any widgets I could add to my blog that automatically tweet my newest twitter updates.

    I’ve been looking for a plug-in like this for quite some time
    and was hoping maybe you would have some experience with something
    like this. Please let me know if you run into anything. I truly enjoy reading your blog and I look forward to your new updates.

  98. I like the valuable information you provide in your articles.
    I’ll bookmark your blog and check again here frequently.
    I’m quite sure I’ll learn a lot of new stuff right here!
    Good luck for the next!

  99. Hi! I could have sworn I’ve visited this website before but after browsing through a few of the posts I realized it’s new to me.
    Anyways, I’m certainly delighted I came across it and I’ll be book-marking it and checking back often!

  100. I blog often and I genuinely appreciate your content. The
    article has really peaked my interest. I will take a note of your website and keep checking for new information about once per
    week. I subscribed to your RSS feed as well.

  101. My brother recommended I might like this web site.
    He was totally right. This post actually made my day.

    You cann’t imagine simply how much time I had spent for this information! Thanks!

  102. Asking questions are actually fastidious thing if you are
    not understanding something totally, but this paragraph offers nice understanding yet.

  103. Hello! I could have sworn I’ve been to this site before but after browsing through some of the post I realized it’s new to me.
    Anyways, I’m definitely glad I found it and I’ll be book-marking and checking
    back often!

  104. My brother recommended I might like this blog.
    He was entirely right. This post actually made my day. You can not imagine just how
    much time I had spent for this information! Thanks!

  105. I am extremely impressed with your writing skills
    and also with the layout on your weblog. Is this a paid theme or did you
    modify it yourself? Anyway keep up the excellent quality writing, it
    is rare to see a nice blog like this one nowadays.

  106. Wow! This blo looks just like my old one! It’s on a
    entirely different topic but it has pretty much the
    same page layout and design. Excellent choice of
    colors!

  107. I’m curious to find out what blog system you’re using?
    I’m having some minor security issues with my latest website and I’d like to find something more safe.

    Do you have any suggestions?

  108. always i used to read smaller content which also clear their motive, and that is also happening with this post which
    I am reading at this time.

  109. I’ll immediately take hold of your rss feed as I
    can not in finding your e-mail subscription hyperlink or newsletter service.

    Do you’ve any? Kindly allow me know so that I may just
    subscribe. Thanks.

  110. I like the valuable information you provide in your articles.
    I’ll bookmark your blog and check again here frequently.
    I’m quite certain I’ll learn many new stuff right here!
    Good luck for the next!

  111. I absolutely love your site.. Pleasant colors & theme.

    Did you build this amazing site yourself? Please reply back as I’m planning to create my own personal site and
    would like to learn where you got this from or just what the theme is called.
    Thanks!

  112. My brother recommended I may like this blog.

    He was once entirely right. This post actually made my
    day. You can not imagine simply how much time I had spent for this information! Thanks!

  113. It’s going to be end of mine day, however before finish I am reading this fantastic article to increase my
    knowledge.

  114. Excellent weblog here! Also your website quite a bit up fast!
    What web host are you using? Can I am getting your affiliate link to
    your host? I desire my site loaded up as quickly as yours lol

  115. whoah this blog is wonderful i really like studying your posts.
    Stay up the great work! You know, lots of persons are searching around for
    this info, you can help them greatly.

  116. Woah! I’m really loving the template/theme
    of this site. It’s simple, yet effective. A lot
    of times it’s difficult to get that “perfect balance” between user friendliness and visual appeal.
    I must say you have done a superb job with this. Also,
    the blog loads extremely fast for me on Firefox. Excellent Blog!

  117. Do you have a spam issue on this blog; I also am a blogger, and I was
    wondering your situation; we have developed some nice procedures
    and we are looking to exchange solutions with others, be sure to
    shoot me an email if interested.

  118. I blog often and I really thank you for your content.
    This article has really peaked my interest. I am going to
    take a note of your site and keep checking for new information about once per week.
    I subscribed to your Feed too.

  119. Sorry I know its off-topic but I just wondered if anyone knows what
    template this site is using ass I really love it thank you

  120. I loved as much as you will receive carried out right here.

    The sketch is attractive, your authored material stylish.
    nonetheless, you command get got an nervousness over that you
    wish be delivering the following. unwell unquestionably come more
    formerly again as exactly the same nearly very often inside case you shield this hike.

  121. I appreciate, lead to I discovered just what I
    used to be looking for. You’ve ended my four day long hunt!
    God Bless you man. Have a great day. Bye

Leave a Reply