Set up a custom domain with Bento and Cloudflare Workers
If you're a creative professional, Bento is a great way to showcase your portfolio and best work. It's easy to set up, free and can be customized to fit many needs. The team is amazing and I've seen so many great designs made on it.
Its only downside, as you may know, is that you can't natively set up a custom domain.
The good news is that it's very easy to set up with your custom domain for free.
Section 1: Prerequisites
Before diving into the setup process, you need:
Registered domain name (Can be with any registrar)
Optional but useful: A basic understanding of JavaScript/TypeScript
Section 2: Initial setup
In our Terminal, let's create a basic Cloudflare Worker:
npm create cloudflare@latest
Now let's just follow the instructions:
In which directory do you want to create your application? Your choice
What type of application do you want to create? "Hello World" Worker
Do you want to use TypeScript? --> No (For this tutorial I went with JavaScript for the sake of simplicity, but I recommend TypeScript if you're comfortable).
Do you want to use git for version control? Yes
Do you want to deploy your application? Yes (it'll ask you to login if you're not logged in already).
Section 3: Setting our environment variables
We'll need to set up our environment variable for development and production.
For production, we need to edit wrangler.toml
:
# Below the current configuration
[vars]
BENTO_USERNAME = "jayfranco" # replace with the name of your Bento page
BASE_URL = "https://jayfran.co" # the custom domain you'll use
For development, we need to create a .dev.vars
file at the root of our project:
BENTO_USERNAME="jayfranco" # replace with the name of your Bento page
BASE_URL="http://127.0.0.1:8787" # one of the default addresses
Section 4: Creating our worker
Our worker will be made of 3 functions all written in our index.js
file
An event listener
addEventListener('fetch', event => { // When a fetch event occurs, responds with the result of the handleRequest function event.respondWith(handleRequest(event.request)); });
A function to parse responses according to their content type
async function parseResponseByContentType(response, contentType) { // If there's no content type, the response is returned as text if (!contentType) return await response.text(); // Depending on the content type, different actions are taken switch (true) { case contentType.includes('application/json'): // If the content type is JSON, the response is returned as a JSON string return JSON.stringify(await response.json()); case contentType.includes('text/html'): // If the content type is HTML, the response is transformed using HTMLRewriter const transformedResponse = new HTMLRewriter() .on('body', { element(element) { // Custom CSS and JS can be added into the body of the HTML element.append( ` <style> // Custom CSS you can add to // modify the styling of your page </style> `, { html: true }, ); element.append( ` <script> // Custom JS you can add to // modify something on your page </script> `, { html: true }, ); }, }) .transform(response); // The transformed response is returned as text return await transformedResponse.text(); case contentType.includes('font'): // If the content type is a font, the response is returned as an ArrayBuffer return await response.arrayBuffer(); case contentType.includes('image'): // If the content type is an image, the response is returned as an ArrayBuffer return await response.arrayBuffer() default: // If the content type is anything else, the response is returned as text return await response.text(); } }
A function to handle all requests
async function handleRequest(request) {
// Extracts the path from the request URL
const path = new URL(request.url).pathname;
// By default, the URL is set to 'https://bento.me'
// appended with the path
let url = 'https://bento.me' + path;
// If the path includes 'v1', the URL is changed to
// 'https://api.bento.me' appended with the path
if (path.includes('v1')) {
url = 'https://api.bento.me' + path;
}
// If the URL is 'https://bento.me/' the URL is changed to
// 'https://bento.me/' appended with the BENTO_USERNAME
if (url === 'https://bento.me/') {
url = 'https://bento.me/' + BENTO_USERNAME;
}
// Basic headers for the fetch request are defined
let headers = {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'GET,HEAD,POST,OPTIONS',
};
// The URL is fetched with the defined headers
const response = await fetch(url, { headers });
// The content type is extracted from the response headers
const contentType = response.headers.get('content-type');
// The response is parsed based on its content type
let results = await parseResponseByContentType(response, contentType);
// If the results are not an ArrayBuffer
// all calls to the bento API are replaced with our BASE_URL
// This is a workaround to fix CORS errors that occur otherwise
if (!(results instanceof ArrayBuffer)) {
results = results.replaceAll('https://api.bento.me', BASE_URL);
}
// The content type is added to the headers
headers['content-type'] = contentType;
// A new response is returned with the results and headers
return new Response(results, { headers });
}
Let's now run our development server and check that everything is working correctly.
npm run dev
Now that everything is working great, let's deploy it to production.
npm run deploy
Section 5: Connecting our custom domain
Last but not least, we need to connect our custom domain.
Once logged into your Cloudflare Dashboard you need to "Add a site" to your Cloudflare account:
a) Choose a plan: Select the plan that you want, the Free plan should work fine for most use cases.
b) Review DNS records: If you have DNS records, it is your time to add them. For example, in my case, I had MX records to set up.
c) Change your nameservers: This step may vary depending on your registrar, but you will want to set your DNS to Custom Nameserver and enter the 2 nameservers given to you by Cloudflare. After that, you can go through with the basic setup given to you by Cloudflare and you just have to wait for everything to propagate. You'll receive an email when it's ready.
d) Set your custom domain: Once everything is propagated and you see your DNS as
Active
on Cloudflare:Select Workers & Pages and in Overview, select your Worker.
Go to Triggers > Custom Domains > Add Custom Domain.
Enter the domain you want to configure for your Worker.
Select Add Custom Domain.
You can now test your domain and it should redirect directly to your Bento page ๐
Conclusion
In conclusion, setting up a custom domain with Bento and Cloudflare Workers offers developers a great combination of flexibility, power, and convenience.
If you have any questions/issues, don't hesitate to DM me on X and I'll assist you with pleasure!
Subscribe to my newsletter
Read articles from Jay Franco directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by