Getting Started
Spry v7 starts with a Dart project, a routes/ directory, and a config file that tells the generated app where it should run.
Install the package
bash
dart pub add spryCreate the runtime config
This is the control plane for local serve and production builds:
dart
import 'package:spry/config.dart';
void main() {
defineSpryConfig(
host: '127.0.0.1',
port: 4000,
target: BuildTarget.dart,
);
}Add your first route
Create routes/index.dart:
dart
import 'package:spry/spry.dart';
Response handler(Event event) {
return Response.json({
'message': 'hello from spry',
'runtime': event.context.runtime.name,
'path': event.request.url.path,
});
}Spry treats this file as the handler for /.
Start the dev server
bash
dart run spry serveBy default, the generated app runs from your current project root and follows the values defined in spry.config.dart.
Grow the route tree
You do not register routes imperatively. You add files:
text
routes/
index.dart
about.get.dart
users/[id].dart
[...slug].dart
_middleware.dart
_error.dartabout.get.dart
dart
import 'package:spry/spry.dart';
Response handler(Event event) {
return Response.json({
'page': 'about',
'method': event.method,
});
}users/[id].dart
dart
// ignore_for_file: file_names
import 'package:spry/spry.dart';
Response handler(Event event) {
final id = event.params.required('id');
return Response.json({
'id': id,
'upper': id.toUpperCase(),
});
}Add middleware and scoped error handling
Middleware and error files are part of the same tree:
_middleware.dart
dart
import 'package:spry/spry.dart';
Future<Response> middleware(Event event, Next next) async {
event.locals.set(#requestId, DateTime.now().microsecondsSinceEpoch.toString());
return next();
}_error.dart
dart
import 'package:spry/spry.dart';
Response onError(Object error, StackTrace stackTrace, Event event) {
if (error case NotFoundError()) {
return Response.json({
'error': 'not_found',
'path': event.request.url.path,
}, status: 404);
}
if (error case HTTPError()) {
return error.toResponse();
}
return Response.json({
'error': 'internal_server_error',
'path': event.request.url.path,
}, status: 500);
}_middleware.dart applies to the current directory scope. _error.dart catches errors raised by routes within the same scope.
Build for production
When you are ready to generate the app entrypoint:
bash
dart run spry buildSpry scans your project and writes the generated runtime output into .spry/ by default.
What to read next
- Project Structure shows how a real Spry project is organized.
- File Routing explains naming, params, wildcard files, and scope rules.
- Middleware and Errors covers cross-cutting request behavior.
- Assets explains static files.
- Lifecycle covers hooks and request order.
- Deploy Overview covers Dart, Node, Bun, Cloudflare Workers, and Vercel.