How to deploy Elysiajs App on CloudFlare Workers

Mert Enercan
3 min readMay 7, 2024

Well, another sleepless night and another tech guide. This time, i’d like to talk about how to deploy an ElysiaJS app with CloudFlare Workers. In this one, i’ll not gonna dig deep the details of ElysiaJS and CloudFlare Workers and will assume that you are already familiar with ElysiaJS and CloudFlare concept. If not, you can take a look to offical ElysiaJS and CloudFlare Workers docs.

Thanks to @sawaratsuki1004 for awesome logo

ElysiaJS

ElysiaJS is a backend framework that works with the power of Bun. It’s 21 times faster than ExpressJS. Also, it has a much better developer experience in my opinion. It has really cool features, so please check out all the examples and official docs from here.

CloudFlare Workers

Well, everybody knows Cloudflare. You can use Workers in many different ways. For example, I've used them as a reverse proxy. In this context, we'll deploy our backend on Workers. We need to install the Wrangler package for programmatically accessing Cloudflare Workers

Hands-On

Well, let’s start from scratch and deploy a ElysiaJS — Pokémon API Endpoint with Cloudflare Workers!

Lets create an ElysiaJS project:

bun create elysia .

Well, since Elysia partially follows WinterCG compliance, it’s optimized for Bun but also openly supports other runtimes such as Cloudflare Runtime. We need to configure our app in some way. Let’s create an index.ts file and modify it like this:

// src/index.ts

import { Env } from "bun"
import { app } from "./app"
import { Context } from "elysia"

export default {
async fetch(
request: Request,
env: Env,
ctx: Context,

): Promise<Response> {

return await app.fetch(request)
},
}

With this configuration, the Cloudflare Worker will recognize our ElysiaJS app and work properly!

Now, lets create routes folder and pokemon.ts file in it.

// src/routes/pokemon.ts

import { Elysia } from 'elysia'

export const pokemonController = new Elysia({ prefix: "/pokemon" })
.get("/:pokemonName", async (context) => {
const { params: { pokemonName } } = context

const pokemonData = await fetch(`https://pokeapi.co/api/v2/pokemon/${pokemonName}`, {
method: 'GET',
headers: {
'Content-Type': 'application/json'
}
})
if (pokemonData.status !== 200) {
throw new Error(await pokemonData.text())
}

return new Response(JSON.stringify({ data: await pokemonData.json() }), { status: 200 })

})

Now we have our Pokémon API endpoint that works dynamically! Notice how we used “:pokemonName” for dynamic endpoints and accessed it via the const { params: { pokemonName } } = context block. It's beautiful.

Prefix option is just one of the coolest features of ElysiaJS!

Now lets back to the src/ folder and create an app.ts file:

// src/routes/app.ts

import Elysia from "elysia";
import { pokemonController } from "./routes/pokemon";


export const app = new Elysia({ aot: false }).onError(({ code, error }) => {
console.log(code)
return new Response(JSON.stringify({ error: error.toString() ?? code }), { status: 500 })
}).use(pokemonController)


app.get('/', () => "Hello from Elysia 🦊")

Another cool feature that Elysia provides is the onError function. We don't need to write response codes for errors in each route. We can simply define a format in the app.ts file, and every endpoint will use it automatically!

Everything should work now. Lets check it locally via command of:

bun run dev

And check your localhost for results

localhost:3000/
localhost:3000/pokemon/snorlax

We are ready to deploy!!

Deployment

As i mentioned before, we need to install Wrangler package and make some configurations.

bun add wrangler
# wrangler.toml

name = "elysia-bun"
compatibility_date = "2023-12-01"

# [vars]
# MY_VAR = "my-variable"

# [[kv_namespaces]]
# binding = "MY_KV_NAMESPACE"
# id = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"

# [[r2_buckets]]
# binding = "MY_BUCKET"
# bucket_name = "my-bucket"

# [[d1_databases]]
# binding = "DB"
# database_name = "my-database"
# database_id = ""

# [ai]
# binding = "AI"

We need to create a wrangler.toml file in the root directory and define the name of our Cloudflare Worker in it. Just copy the code below and change the values accordingly:

Last but not least, we need to set a command for deploying our app.

"deploy": "wrangler deploy --minify src/index.ts"

You can place this code to the package.json file (scripts scope).

And we are done!!! Lets deploy our Elysia app

bun run deploy

If this is your first time using Wrangler, it’ll probably ask you for authentication. Just follow the instructions, and you’re good to go!

Here is the live version : https://elysia-bun.merto.workers.dev/pokemon/snorlax

Here is the github repo: https://github.com/mertthesamael/elysia-cf-worker

Here is my Website: https://www.merto.dev/

Until next time!

Do not forget to drink at least 2L of water/day.

--

--