A comprehensive tutorial project demonstrating how to build a RESTful API backend using Dart Frog, a fast and minimalistic backend framework for Dart.
- Features
- Prerequisites
- Getting Started
- Project Structure
- API Endpoints
- Development
- Flutter Frontend Integration
- Testing
- License
- RESTful API with CRUD operations
- Todo Management System with create, read, update, and delete functionality
- User Management endpoints
- Authentication with JWT and BCrypt
- Middleware Support for logging, CORS, and authentication
- In-memory data storage for learning purposes
- Clean architecture with repository pattern
- Comprehensive test coverage
- Hot reload for rapid development
Before you begin, ensure you have the following installed:
- Dart SDK (>=3.0.0)
- Dart Frog CLI
Install Dart Frog CLI:
dart pub global activate dart_frog_cli- Clone the repository:
git clone https://github.com/techwithsam/dart_frog_full_course_tutorial
cd dart_frog_full_course_tutorial- Install dependencies:
dart pub get- Start the development server:
dart_frog devThe server will start on http://localhost:8080.
my_project/
βββ lib/
β βββ src/
β βββ constant.dart # Constants (JWT Secret)
β βββ todo_model.dart # Todo data model
β βββ todo_repository.dart # Todo data access layer
β βββ user_model.dart # User data model
β βββ user_repository.dart # User data access layer
βββ routes/
β βββ index.dart # Root endpoint (GET /)
β βββ auth/
β β βββ login.dart # User login (POST /auth/login)
β β βββ register.dart # User registration (POST /auth/register)
β βββ todos/
β β βββ _middleware.dart # Middleware (Auth, CORS, Logging)
β β βββ index.dart # Todo list operations (GET, POST /todos)
β β βββ [id].dart # Individual todo operations (GET, PUT, DELETE /todos/:id)
β βββ users/
β βββ index.dart # User operations (GET, POST /users)
βββ test/
β βββ routes/
β βββ index_test.dart # Route tests
βββ analysis_options.yaml # Dart analyzer configuration
βββ pubspec.yaml # Project dependencies
βββ README.md # This file
Returns a welcome message.
Response:
{
"message": "Hello Flutter World from Dart Frog! πΈ"
}Register a new user.
Request Body:
{
"username": "user1",
"password": "password123"
}Response:
{
"id": "uuid",
"username": "user1"
}Login and receive a JWT.
Request Body:
{
"username": "user1",
"password": "password123"
}Response:
{
"token": "eyJhbGciOiJIUz..."
}Note: All
/todosendpoints look for a valid JWT in theAuthorizationheader:Bearer <token>.
Retrieve all todos.
Response:
[
{
"id": "1",
"title": "Learn Dart Frog",
"isCompleted": false
}
]Create a new todo.
Request Body:
{
"title": "My new todo"
}Response:
Status: 201 Created
Body: "Todo created"
Retrieve a specific todo by ID.
Response:
{
"id": "1",
"title": "Learn Dart Frog",
"isCompleted": false
}Update a todo.
Request Body:
{
"title": "Updated title",
"isCompleted": true
}Response:
{
"id": "1",
"title": "Updated title",
"isCompleted": true
}Delete a todo.
Response:
Status: 204 No Content
Retrieve all users.
Response:
[
{ "id": 1, "name": "Alice" },
{ "id": 2, "name": "Bob" },
{ "id": 3, "name": "Charlie" }
]Create a new user.
Request Body:
{
"name": "David"
}Response:
{
"id": 4,
"name": "David"
}dart_frog devThis starts the server with hot reload enabled. Changes to your code will automatically reload the server.
dart_frog buildThis creates a production-ready build in the build directory.
dart build/bin/server.dartThis Dart Frog backend can be easily connected to a Flutter frontend application. The flutter_todo_dart_frog directory contains a complete Flutter app example that demonstrates how to interact with this API.
- Update your API base URL:
In your Flutter app's HTTP client configuration, set the base URL to your Dart Frog server:
const String apiBaseUrl = 'http://localhost:8080';- Make HTTP requests:
import 'package:http/http.dart' as http;
// Get all todos
Future<List<Todo>> fetchTodos() async {
final response = await http.get(
Uri.parse('$apiBaseUrl/todos'),
);
if (response.statusCode == 200) {
final List<dynamic> jsonData = jsonDecode(response.body);
return jsonData.map((json) => Todo.fromJson(json)).toList();
} else {
throw Exception('Failed to load todos');
}
}
// Create a new todo
Future<void> createTodo(String title) async {
final response = await http.post(
Uri.parse('$apiBaseUrl/todos'),
headers: {'Content-Type': 'application/json'},
body: jsonEncode({'title': title}),
);
if (response.statusCode != 201) {
throw Exception('Failed to create todo');
}
}
// Update a todo
Future<void> updateTodo(String id, String title, bool isCompleted) async {
final response = await http.put(
Uri.parse('$apiBaseUrl/todos/$id'),
headers: {'Content-Type': 'application/json'},
body: jsonEncode({
'title': title,
'isCompleted': isCompleted,
}),
);
if (response.statusCode != 200) {
throw Exception('Failed to update todo');
}
}
// Delete a todo
Future<void> deleteTodo(String id) async {
final response = await http.delete(
Uri.parse('$apiBaseUrl/todos/$id'),
);
if (response.statusCode != 204) {
throw Exception('Failed to delete todo');
}
}- Handle network requests:
For production environments, update your API URL to point to your deployed server:
const String apiBaseUrl = 'https://your-production-url.com';The Flutter frontend integrating with this Dart Frog backend:
Run all tests:
dart testRun tests with coverage:
dart test --coverage=coverage
dart pub global activate coverage
dart pub global run coverage:format_coverage --lcov --in=coverage --out=coverage/lcov.info --report-on=libContributions are welcome! Please feel free to submit a Pull Request.
This project is licensed under the MIT License - see the LICENSE file for details.


