Skip to content

techwithsam/dart_frog_full_course_tutorial

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

7 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Dart Frog Full Course Tutorial

style: dart frog lint License: MIT Powered by Dart Frog

A comprehensive tutorial project demonstrating how to build a RESTful API backend using Dart Frog, a fast and minimalistic backend framework for Dart.

πŸ“‹ Table of Contents

✨ Features

  • 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

πŸ”§ Prerequisites

Before you begin, ensure you have the following installed:

Install Dart Frog CLI:

dart pub global activate dart_frog_cli

πŸš€ Getting Started

  1. Clone the repository:
git clone https://github.com/techwithsam/dart_frog_full_course_tutorial
cd dart_frog_full_course_tutorial
  1. Install dependencies:
dart pub get
  1. Start the development server:
dart_frog dev

The server will start on http://localhost:8080.

πŸ“ Project Structure

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

🌐 API Endpoints

Root

GET /

Returns a welcome message.

Response:

{
  "message": "Hello Flutter World from Dart Frog! 🐸"
}

Auth

POST /auth/register

Register a new user.

Request Body:

{
  "username": "user1",
  "password": "password123"
}

Response:

{
  "id": "uuid",
  "username": "user1"
}

POST /auth/login

Login and receive a JWT.

Request Body:

{
  "username": "user1",
  "password": "password123"
}

Response:

{
  "token": "eyJhbGciOiJIUz..."
}

Todos

Note: All /todos endpoints look for a valid JWT in the Authorization header: Bearer <token>.

GET /todos

Retrieve all todos.

Response:

[
  {
    "id": "1",
    "title": "Learn Dart Frog",
    "isCompleted": false
  }
]

POST /todos

Create a new todo.

Request Body:

{
  "title": "My new todo"
}

Response:

Status: 201 Created
Body: "Todo created"

GET /todos/:id

Retrieve a specific todo by ID.

Response:

{
  "id": "1",
  "title": "Learn Dart Frog",
  "isCompleted": false
}

PUT /todos/:id

Update a todo.

Request Body:

{
  "title": "Updated title",
  "isCompleted": true
}

Response:

{
  "id": "1",
  "title": "Updated title",
  "isCompleted": true
}

DELETE /todos/:id

Delete a todo.

Response:

Status: 204 No Content

Users

GET /users

Retrieve all users.

Response:

[
  { "id": 1, "name": "Alice" },
  { "id": 2, "name": "Bob" },
  { "id": 3, "name": "Charlie" }
]

POST /users

Create a new user.

Request Body:

{
  "name": "David"
}

Response:

{
  "id": 4,
  "name": "David"
}

πŸ’» Development

Running in Development Mode

dart_frog dev

This starts the server with hot reload enabled. Changes to your code will automatically reload the server.

Building for Production

dart_frog build

This creates a production-ready build in the build directory.

Running the Production Build

dart build/bin/server.dart

πŸ“± Flutter Frontend Integration

This 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.

Connecting Your Flutter App

  1. 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';
  1. 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');
  }
}
  1. Handle network requests:

For production environments, update your API URL to point to your deployed server:

const String apiBaseUrl = 'https://your-production-url.com';

Screenshots

The Flutter frontend integrating with this Dart Frog backend:

Todo App Screenshot 1

Todo App Screenshot 2

Todo App Screenshot 3

πŸ§ͺ Testing

Run all tests:

dart test

Run 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=lib

πŸ“ Learning Resources

🀝 Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

πŸ“„ License

This project is licensed under the MIT License - see the LICENSE file for details.