/

Engineering

Jan 23, 2025

Jan 23, 2025

How to build a server in Dart: CTO insights

Learn how to build a server in Dart with expert insights from a CTO. Discover step-by-step guidance to create efficient and scalable servers using Dart.

A bit about me before we dive in. I am CTO at Pieces for Developers, and I have been in software for roughly 10 years now working mainly on backend + cloud infrastructure everything from (local/cloud server, and database infrastructure, and generally anything and everything to do with Backend development).

Throughout this tutorial series I will be referencing Pieces for Developers, our main goal is building long-term memory for developers intractable via a Conversation form factor using the cloud LLM of your choosing

Using Pieces is not required for this tutorial series, however, if you want to further your development skills, and reduce context switching while using the power of Long Term Memory then I would recommend taking a look at Pieces for Developers and our lengthy list of products.


Getting started 

Have you ever wondered how services like Stripe, SendGrid, and many others implement their backend? If so, this is the right article for you! 

One of the key components of a backend is rest API and, specifically an HTTP (or RPC) server that will accept these requests. 

Today, we will build a local HTTP server using pure Dart and an awesome Dart package called Shelf Plus. We will set up our project, set up our server, and add a single health check route. There are plenty more topics to dive into, like middleware, streaming, persistence, automated testing, and much more, but we’ll save these topics for future blog posts!


Step 1: Create a new repository

Let’s start by creating a brand new repository written in Dart. For this, ensure that you have Flutter installed, open up your favorite IDE (I prefer IntelliJ) in a brand new directory, and we are ready to Rock🤘

Create your first file, pubspec.yaml. Let’s add the following code to the pubspec.yaml file:

name: how_to_build_a_dart_server
description: A New local Dart Server
version: 1.0.0 

environment:
  sdk: ">=3.3.0 <4.0.0" 

dependencies:
  shelf_plus

As you see, we have a pretty empty pubspec with just a few things to note. 

First, our environment will need to encapsulate your specific version of Dart. 

For instance, I am on Dart version 3.4.4, and this version will fall within the bounds of our version here. Secondly, a lot goes into building a server from scratch, like request routing and handling, concurrency and long-running tasks, port binding, and server management–just to name a few. 

To keep things straightforward, let's skip over these parts and use an awesome package(shelf_plus), so we can jump into the fun stuff. If you want to learn a little more about packages in Dart here is a great article. This gives us the ability to have a long-running HTTP server that serves a specified port with a series of specified routes.



Step 2: Set up your project structure

  1. Run a `Flutter pub get` in our project to get all of our dependencies.

  2. Create a ‘lib’ folder with 2 files, a main.dart and a file called initialize_routes.dart.

  3. Our project should look a little like the Figure below (without the .idea folder, most likely).

Next, let's boot up our server and add our first route (our health check). For this, let’s start with our main.dart file, which is the entry point to any Flutter/Dart project. Then, let’s add the following code:

import 'package:how_to_build_a_dart_server/initialize_routes.dart';
import 'package:shelf_plus/shelf_plus.dart'

As we can see here, we will have two imports ShelfPlus ‘shelfRun’ this will start our server by providing a function that will initialize our routes. The shelfRun function enables us to configure a bunch of things, like a specified port, handling graceful shutdowns, and a bunch of other utilities that can be explored further here

We are also importing a function called initializeRoutes from our local repository (currently, I have my import set to absolute paths, but can also use relative paths here ie `import ‘../initialize_routes.dart’;`). Note: ‘building_a_local_dart_server’ is the name of the current package within the pubspec.yaml. 

This function, initializeRoutes, will define the set of routes that we will need to get our server fully functional–but let's start with the health check and verify everything is up and running.

import 'package:shelf_plus/shelf_plus.dart';

/// The goal of this function will be to add all our endpoints to our router
/// so that when our endpoint are called we can properly handle each request.
Handler initializeRoutes() {

  // get our router
  RouterPlus app = Router().plus;

  // add our GET endpoint for well-known
  app.get('/.well-known/health', (Request request) {
    // this is a specific handler for this given request
    // IE when ever this endpoint is called, this function will be executed
    
    // add a print statement to see this was called:)
    print('well known called!');
    
    // return a statuscode: 200 + and response of 'ok' to the cliet
    return Response(
      200,
      body: 'ok',
    );
  });

  return app.call;
}

This code will define a function called ‘initializeRoutes’ that will return a handler that will be provided to the server in the main.dart file. 

In the function body, we will create a new instance of our Router, and we will define a GET request, at the route ‘’/.well-known/health”. 

Next, we’ll pass in a function to our get request that will handle the request ie whenever someone makes a request to this endpoint we will run the following code. The code will accept a request, which is the request from the ‘client’ that makes a request to your server, we will print to the console saying that “well known” was called, then we will return a 200 status code with a body in the request just return a string of ‘ok’.


Step 3: Run and test your server

Now to ensure that everything is running properly, let's run our server and simulate a client-side request. To do this let's first navigate to our terminal or command line in the specified directory of the project, then run another `pub get` to ensure our packages are up to date, and run a `dart run` via the following commands.


After you run this you should see the following in your terminal:

[hotreload] Hot reload not enabled. Run this app with --enable-vm-service (or use debug run) in order to enable hot reload.
shelfRun HTTP service running on port 8080

Next, let's make our Request! Since we are just using a GET request, which requires no input in the request body, we can just navigate to your preferred browser and paste in the following URL:

If this works properly, you should see ‘ok’ on your browser window, and you should see “well-known called!” in your terminal. This means you have successfully built a local server in Dart

Here is a link to the repository & the Part 1 commit. In this article, we created our dart project, added our shelf_plus dependency, and initialized our project with 2 files–our main.dart which is the entry point, and our initialize_routes.dart file with just a single GET request. In the next article, we’ll add GET, POST, and DELETE requests to showcase all our CRUD operations, as well as automated tests to ensure that everything is running properly.

If you liked this article, you might find the other ones useful too:

Written by

Written by

SHARE

How to build a server in Dart: CTO insights

Title

Title

our newsletter

Sign up for The Pieces Post

Check out our monthly newsletter for curated tips & tricks, product updates, industry insights and more.

our newsletter

Sign up for The Pieces Post

Check out our monthly newsletter for curated tips & tricks, product updates, industry insights and more.

our newsletter

Sign up for The Pieces Post

Check out our monthly newsletter for curated tips & tricks, product updates, industry insights and more.