Simple GUIDE – Create a bun Server with Elysia Framework

Introduction

This article will show you how to create a server using the Elysia Framework for bun JS. By the end you will know about the following features:

  • Basic setup and server scaffolding
  • Get requests with URL parameters
  • Post requests with body data
  • Architecture for organising your routes
  • Sending responses to the end user

I won’t cover anything generic such as database connections so that we can concentrate on the topic at hand. That said, it’s important to remember that bun is a drop in replacement for node js, so any business logic you need can simply be copy pasted from a node implementation with zero compatibility issues!

Setup bun and Create Elysia App

The first step is to setup bun and create the Elysia app.

  1. Open up Visual Studio Code
  2. Open your working folder with “File => Open Folder”
  3. Open a terminal with “Terminal => New Terminal”
  4. In terminal type: “bun create Elysia myApp” (myApp is the name of your app)
  5. Follow the onscreen instructions, simply accepting the defaults

Run Elysia Server

Now that your Elysia server has been created you should test it out. By default an npm script to run the server should be in package.json under the scripts section:

“scripts”: {
“test”: “echo \”Error: no test specified\” && exit 1″,
“dev”: “bun run –watch src/index.ts”
},

If this is not there then go ahead and add it. Then in your terminal run:

npm run dev

You should see “Elysia is running at localhost:3000” in the terminal. Use your browser to go to localhost:3000 and you should see a welcome message corresponding to what’s in your index.ts server declaration code.

Create a Get Route in Elysia

Before we start, a word on architecture … one option to create your get route is just to place it straight into the index.ts file but after adding a couple of routes that would really clutter up the index file! Let’s use good architecture practice instead:

  1. Create a “routes” folder in the “src” folder.
  2. Create a “shop.ts” file in that routes folder.

This shop.ts file will hold all the routes corresponding to our pseudo online shopping server. Open that file and paste in the following code:

import { Elysia } from "elysia";

const shopRoutes = new Elysia({ prefix: '/shop' })
.get('/', () => 'HOME PAGE for shop, welcome')

export default shopRoutes;

A couple of notes on the above code:

We first import the Elysia class as it contains everything we need to define all things “server”. Then we define a constant called “shopRoutes” which will hold all of our routes. This takes an optional object in which we can define things such as the URL prefix. In this case we have defined “/shop” so this route group will only be called if the URL entered has this form:

Eg: localhost:3000/shop

You should have noticed that the server auto reloads when you save any code. The –watch option in the dev script watches all our code, automatically reloading when required!

Although if we tried this route now it wouldn’t work as we need to specify that these routes exist in the index.ts file.

Add Route Groups to Elysia

Open up the index.ts file and clear out all the boilerplate code. Paste in the following lines:

import { Elysia } from "elysia";
import shopRoutes from "./routes/shop"

const app = new Elysia()
app
  .group('', (app) => app.use(shopRoutes)) //ADDITION OF ROUTE GROUPS
  .listen(process.env.PORT || 3000);

console.log(
  `🦊 Elysia is running at ${app.server?.hostname}:${app.server?.port}`
);

Our “shopRoutes” are imported at the top of file which can then be used the .group function. This registered those routes with the main Elysia object.

Now open up any browser and navigate to localhost:3000/shop to see your GET request in action!

Add URL Parameters to an Elysia GET Route

On a server you will need a way to retrieve data based on some variable passed in from the client. For example, in our shop we may want to retrieve a product based on a code or product name. Usually this is specified in a GET route using a URL parameter, ie a subsection of the URL. The example below will take the last part of the URL as a variable which is used to find product information and return it:

myshop.com/shop/butter => Should return a page for butter
myshop.com/shop/ribeye => Should return a page for ribeye steak

This is pretty easy to implement in Elysia. Let’s open up the routes/shop.ts file and add a second GET route as marked below:

import { Elysia } from "elysia";

const shopRoutes = new Elysia({ prefix: '/shop' })
  .get('/', () => 'HOME PAGE for shop, welcome')
  .get('/:item', ({ params: params }) => "Returned data for: " + params.item) //ADD THIS LINE

export default shopRoutes;

Test it out by going to localhost:3000/shop/shampoo. You should get “Returned data for shampoo” in your browser!

Let’s now step through this GET request so you understand it fully. The URL is defined as having a variable with the colon character ( : ). Any name after that will be the variable name but you have to explicitly pass the params to the response function! This is done with the { params: params } argument, then the anonymous function will have access to your variables.

Note that the above is a shortened version of reality. You would normally be doing a database lookup somewhere based on the variable (usually an id that is passed over).

Create a POST Route with Body Data in Elysia

As you probably know POST routes differ from GET routes as the former sends structured data along with the request. Usually this data would be too complex to include in a GET parameter so instead is bundled into the BODY of the POST request.

Using the routes/shop.ts we already have in place we will add a POST route that allows us to send over some data about a users cart. Start by adding a route as below:

import { Elysia } from "elysia";

const shopRoutes = new Elysia({ prefix: '/shop' })
  .get('/', () => 'HOME PAGE for shop, welcome')
  .get('/:item', ({ params: params }) => "Returned data for: " + params.item)
  .post('/cart', ({ body }) => JSON.stringify(body)) //ADD THIS LINE

export default shopRoutes;

Now there are tools in Chrome that you can use to send a POST request but for sake of speed we’ll issue a curl command (on Linux / Mac). Simply copy and paste the following into your terminal:

curl localhost:3000/shop/cart -X POST -H “Content-Type: application/json” -d ‘{“id”: “Bread”, “count”: 9}’

When we send over our CURL request when also send some body data with the type “application/json” (defined in the header -H). The body data is defined after the -d flag in the curl command.

Our application picks up the body, converts it to a string using JSON.stringify and sends it back to us. In reality you’d actually use this data to calculate the cart price or whatever your application needs.

Finally

If you liked this then you’ll love my full bun and Elysia course. Check it out here.

Appendix: Full Code

Here’s the code from index.ts

import { Elysia } from "elysia";
import shopRoutes from "./routes/shop"

const app = new Elysia()
app
  .group('', (app) => app.use(shopRoutes))
  .listen(process.env.PORT || 3000);

console.log(
  `🦊 Elysia is running at ${app.server?.hostname}:${app.server?.port}`
);

And here’s the code for routes/shop.ts

import { Elysia } from "elysia";

const shopRoutes = new Elysia({ prefix: '/shop' })
  .get('/', () => 'HOME PAGE for shop, welcome')
  .get('/:item', ({ params: params }) => "Returned data for: " + params.item)
  .post('/cart', ({ body }) => JSON.stringify(body))

export default shopRoutes;

Don’t forget to see the full course!

Leave a Comment