Lesson 23 / 25
Dart on the Server and the Command Line
Build CLIs and HTTP servers in Dart, with JSON serialisation.
Beyond mobile apps
Dart is a capable language for command-line tools and backend services, especially for teams already using Flutter who want to share models and validation code. For CLIs, package:args parses flags and subcommands, dart:io handles files, processes and stdin/stdout, and dart compile exe produces a single binary. For HTTP servers, package:shelf provides composable handlers and middleware with routing via shelf_router, and frameworks such as Dart Frog and Serverpod offer more structure, code generation and full-stack features. Server code uses the same async model: each request handler returns a Future<Response>, and multiple isolates can serve requests on several cores. For JSON, small projects map manually with fromJson/toJson, while larger ones use json_serializable (annotations plus build_runner) or freezed (immutable data classes with unions). Deploy native executables in small containers on Cloud Run, Kubernetes or any VM.
A small shelf API
Routing, JSON responses and logging middleware.
import 'dart:convert';
import 'dart:io';
import 'package:shelf/shelf.dart';
import 'package:shelf/shelf_io.dart' as io;
import 'package:shelf_router/shelf_router.dart';
final _orders = <String, Map<String, Object>>{
'o-1': {'id': 'o-1', 'status': 'paid', 'total_paise': 49900},
};
Response _json(Object body, {int status = 200}) => Response(
status,
body: jsonEncode(body),
headers: {'content-type': 'application/json'},
);
Future<void> main() async {
final router = Router()
..get('/health', (Request _) => _json({'status': 'ok'}))
..get('/orders/<id>', (Request request, String id) {
final order = _orders[id];
return order == null ? _json({'error': 'Not found'}, status: 404) : _json(order);
});
final handler = const Pipeline().addMiddleware(logRequests()).addHandler(router.call);
final port = int.parse(Platform.environment['PORT'] ?? '8080');
final server = await io.serve(handler, InternetAddress.anyIPv4, port);
print('Listening on ${server.address.host}:${server.port}');
}One toolbox for the whole house
Using Dart on both the app and the server is like using one set of tools for every room: the same measurements (models), the same screwdrivers (validation code), and fewer chances of parts not fitting together.
Quick check: Which package provides composable HTTP handlers and middleware for Dart servers?
- package:args
- package:shelf
- package:test
- package:lints
Answer
package:shelf — shelf is the foundational package for HTTP servers in Dart.