Skip to content

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 spry

Create 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 serve

By 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.dart

about.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 build

Spry scans your project and writes the generated runtime output into .spry/ by default.

Released under the MIT License.