If you've ever built a backend in PHP (Laravel) or Ruby (Rails), you know the feeling of "it just works." You have a router, a database ORM, authentication, and a template engine all ready to go.
In the Dart ecosystem, we often piece these things together manually using shelf or bare-bones HTTP servers.
Enter Archery.
Archery is a new, batteries-included web framework for Dart that aims to bring that developer-first, "Laravel-like" experience to the Dart language.
Why Archery?
Dart is an incredible language for the backend—it's typed, fast (AOT compiled), and has great async support. But the ecosystem has lacked a cohesive framework that standardizes how we build apps.
Archery fills that gap by providing:
- Dependence Injection (IoC): A powerful container that manages your application's services.
- Expressive Routing: Define routes with types, groups, and middleware.
- Active Record ORM: Persist objects to JSON files (for prototyping) or SQLite/Postgres (for production) with a single API.
- Blade-style Templates: Write HTML views with
@if,@foreach, and layouts. - Authentication: Built-in session management and auth/guest guards.
A Quick Taste
Here is what a typical route looks like in Archery. It feels familiar, readable, and robust.
dart
// lib/src/http/routes/web.dart
void webRoutes(Router router) {
// Simple View Return
router.get('/', (request) async {
return request.view('welcome', {'app_name':'Archery'});
});
// Typed Parameters & Controller
router.get('/users/{id:int}', UserController.show);
// Grouped Routes with Middleware
router.group(prefix:'/admin', middleware: [Auth.middleware], routes: () {
router.get('/dashboard', (request)async {
final user= await Auth.user(request);
return request.view('admin.dashboard', {'user': user});
});
});
}
The "Object Persistence" Philosophy
One of Archery's most interesting design choices is its approach to data. Instead of a heavy, complex ORM configuration, Archery focuses on Object Persistence.
You define a model, and you can save it to a disk (JSON) or a database (SQLite) using the same simple API.
dart
// Create a user
final user = User(name:"Kwame", email:"kwame@archery.dev");
// Save it! (Default disk is defined on Model)
await user.save();
// Save it to another disk
await user.save(disk: .sqlite);
final sqliteUser = Model.find<User>(id: 1, disk: .sqlite);
// S3 and File drivers use UUID as id
final s3User = Model.find<User>(id: "uuid-goes-here", disk: .s3);
final pgsqlUser = Model.find<User>(id: 1, disk: .pgsql);
This makes prototyping insanely fast. You can start with a JSON-file database and switch to Postgres later by changing one line of config.
Getting Started
Archery is designed to be picked up in minutes.
- Clone the repo:
git clone <https://github.com/webarchery/archery> - Install deps:
dart pub get - Run it:
dart run bin/server.dart
Visit http://localhost:5501 and you'll see the welcome screen.
Conclusion
Archery isn't trying to replace the low-level ecosystem; it's building on top of it to give application developers a comfortable, productive home. If you want to write full-stack Dart apps without reinventing the wheel every time, give Archery a shot.