Gisila framework
gisila is a small, opinionated web framework for Dart servers, built on Shelf. You write thin controller classes with annotations; a build_runner generator turns them into routes with parameter binding, validation, permission checks and per-route limits. Everything around the routes (auth, CORS, rate limiting, security headers, logging, metrics, database sessions, graceful shutdown) is configured in one AppConfig.
Install
Section titled “Install”dependencies: gisila: ^0.4.1
dev_dependencies: build_runner: ">=2.5.0 <3.0.0"package:gisila/gisila.dart is the only import you need in application code; it re-exports the parts of shelf and shelf_router that controllers use.
A 30-second example
Section titled “A 30-second example”import 'package:gisila/gisila.dart';
part 'users_controller.g.dart';
class CreateUserForm extends Form { final email = EmailField(name: 'email', required: true); final name = StringField(name: 'name', required: true, maxLength: 100);
@override List<FormField<Object?>> collectFields() => [email, name];}
@Controller('/users')@RequireAuth()class UsersController { @Get('/{id}') @Permissions({'users:read'}) Future<Map<String, Object?>> show(String id, RequestContext ctx) async => {'id': id, 'requestedBy': ctx.principal!.id};
@Post('/') @Permissions({'users:write'}) Future<Map<String, Object?>> create(CreateUserForm form) async => {'email': form.email.value, 'name': form.name.value};}import 'package:gisila/gisila.dart';import 'package:my_api/controllers/users_controller.dart';
Future<void> main() async { final app = GisilaApp( config: AppConfig( authenticator: const StaticTokenAuthenticator({ 'dev-token': Principal(id: 'dev', permissions: {'users:read', 'users:write'}), }), ), ); app.registerController(attacher: UsersController().attachToApp); await app.start(port: 8080, stopOnSignals: true);}dart run build_runner build --delete-conflicting-outputsdart run bin/server.dartcurl -H 'authorization: Bearer dev-token' localhost:8080/users/7# {"id":"7","requestedBy":"dev"}id comes from the path, the form is parsed and validated before your method runs, missing credentials answer 401, missing permissions 403, and @Post answers 201.
When to use gisila
Section titled “When to use gisila”- JSON APIs and backends in Dart, especially alongside Flutter apps that share models.
- Teams that want routes, validation and access rules declared next to the code, with the wiring generated rather than hand-written.
- Services that need production basics (auth, rate limits, security headers, structured logs, metrics, graceful shutdown) without assembling them from separate packages.
- Projects using the rest of the Gisila stack: gisila_orm for Postgres, gisila_queue for background jobs, gisila_doc for OpenAPI specs, gisila_studio for an admin, and the panel to deploy.
When not to use it
Section titled “When not to use it”- You want no code generation. gisila’s routing depends on
build_runner. Plainshelf_routergives you hand-written routing with nothing generated. - Server-rendered HTML sites. gisila can serve static files and return any
Response, but it has no templating, sessions or CSRF protection built in. - Unusual routing (regex paths, content negotiation per route). Possible with hand-written handlers inside a gisila app, but that is not where the framework helps.
How the section is organised
Section titled “How the section is organised”ConceptsHow requests flow, and when to use controllers, forms, services, permissions, configuration and codegen.
GuidesStep-by-step how-tos: create a project, build a CRUD API, add auth, test, deploy.
API referenceEvery public symbol, grouped by area, with signatures, defaults and when to use it.
Concepts
Section titled “Concepts”- Request lifecycle: the pipeline from socket to controller and back.
- Controllers: method signatures as the contract.
- Forms and validation: typed input and one error shape.
- Services and dependency scopes: request-scoped services and app-wide singletons.
- Authentication and permissions: authenticators, resolvers and guards.
- Configuration:
AppConfigand layeredRouteConfig. - Code generation: what the generator does and why.