Annotated Shelf

Powerful, Lightweight, Fast development, Easy to learn


Annotated Shelf is a powerful and lightweight Dart framework for generating REST APIs using annotations. Based on the popular Shelf library. Annotated Shelf provides a simple and intuitive interface for building APIs fast, efficiently, and easy to use without losing what Shelf can offer.


  • Support for multiple HTTP methods and request types.
  • Support for File upload.
  • Automatic validation of request parameters.
  • Automatic Error responses based on exceptions.


To install Annotated Shelf, add it as a dependency in your pubspec.yaml file:

  annotated_shelf: ^0.1.0

Then, run pub get to install the package.

Getting Started

To use Annotated Shelf to create a REST API, import the library and annotate your models and controllers with the following annotations:


Annotated Shelf will automatically generate the necessary routes and endpoints based on the annotations you have provided.


import 'package:annotated_shelf/annotated_shelf.dart';
import 'package:shelf/shelf.dart';
import 'package:shelf/shelf_io.dart' as io;

const _hostname = 'localhost';
const _port = 8080;
var itemsList = [Item("first item"), Item("second Item")];

class Item extends Payload {
  final String? name;


  factory Item.fromJson(Map<String, dynamic> json) {
    return Item(json["name"]);
  Map<String, dynamic> toJson() => {"name": name};

class TestForm extends Form {
  String name;
  int number;
  File image;

  TestForm(, this.number, this.image);

  factory TestForm.fromJson(Map<String, dynamic> json) {
    return TestForm(
      json['name'] as String,
      json['number'] as int,
      File.fromJson(json['image'] as Map<String, dynamic>),

  Map<String, dynamic> toJson() => <String, dynamic>{
        'name': name,
        'number': number,
        'image': image,

@RestAPI(baseUrl: '/to-do/list')
class ItemsAdaptor {
  List<Item> getAllItems(Request request) {
    return itemsList;

  @GET(url: "/<itemName>")
  Item getItemByName(String itemName) {
    var index = itemsList.lastIndexWhere((element) => == itemName);
    if (index >= 0) {
      return itemsList[index];
    } else {
      throw NotFoundError('item not found'); // this creates a 404 response

  @PUT(url: "/<itemName>")
  Item updateItem(Item item, String itemName) {
    var index = itemsList.lastIndexWhere((element) => == itemName);
    if (index >= 0) {
      itemsList[index] = item;
      return getItemByName( ?? '');
    } else {
      throw NotFoundError('item not found'); // this creates a 404 response

  @POST(url: "/")
  Response createNewItem(Item item) {
    var index =
        itemsList.lastIndexWhere((element) => ==;
    if (index == -1) {
      return Response(201); // pass a shelf response
    } else {
      throw BadRequestError('item with name in list');

  // examplo of uploading a file
  @POST(url: '/upload')
  Future<RestResponse> upload(TestForm form) async {
    return new RestResponse(201, {"msj": 'ok'}, "application/json");

Future<void> main(List<String> args) async {
  var router = Cascade();

  router = await mount(ItemsAdaptor(), router);

  var server = await io.serve(router.handler, _hostname, _port);
  print('Serving at http://${}:${server.port}');

mounting Instance of 'ItemsAdaptor'
adding get to-do/list
adding get to-do/list/<iteName>
adding put to-do/list/<iteName>
adding post to-do/list/
adding post to-do/list/upload
Serving at http://localhost:8080


We welcome contributions to Annotation Shelf! If you have an idea for a new feature or have found a bug, please open an issue on GitHub.


Annotation Shelf is released under the BSD-3-Clause. See LICENSE for details.


Special thanks to the Shelf project team for providing us with the opportunity to create servers using this beautiful language.


Helps to create the REST API