smithery/pluginagentmarketplace

custom-plugin-flutter-skill-backend

1500+ lines of backend integration mastery - REST APIs, GraphQL, WebSockets, authentication, Firebase, error handling with production-ready code examples.

Installation

$ npx skills add smithery/pluginagentmarketplace --skill custom-plugin-flutter-skill-backend

Similar popular skills

Related neighbors and high-traction skills in the same topics — useful to compare before installing.

Also in this package

Other skills from smithery/pluginagentmarketplace · top by installs.

npx skills add smithery/pluginagentmarketplace

Browse all from smithery/pluginagentmarketplace

More details

Agent compatibility

Declared targets from SKILL.md / docs. Unmarked agents are not listed — the skill may still install via the CLI.

Claude Code Not declared
Cursor Not declared
Codex Not declared
GitHub Copilot Not declared
Windsurf Not declared
Gemini CLI Not declared
Cline Not declared
OpenCode Not declared

Package contents

Files included with this skill beyond the listing page.

  • skill md SKILL.md 8,442 B
  • docs SUMMARY.md 197 B

History

  1. First recorded snapshot · 0 installs

SKILL.md

custom-plugin-flutter: Backend Integration Skill

Quick Start - Dio Client

final dio = Dio(BaseOptions(
  baseUrl: 'https://api.example.com',
  connectTimeout: Duration(seconds: 10),
  receiveTimeout: Duration(seconds: 10),
));

// Add logging interceptor
dio.interceptors.add(LoggingInterceptor());

// Make request
Future<User> getUser(String id) async {
  try {
    final response = await dio.get('/users/$id');
    return User.fromJson(response.data);
  } on DioException catch (e) {
    throw ApiException(e.message ?? 'Unknown error');
  }
}

1. HTTP Clients

HTTP Package (Lightweight):

import 'package:http/http.dart' as http;

Future<User> getUser(String id) async {
  final response = await http.get(
    Uri.parse('https://api.example.com/users/$id'),
    headers: {'Authorization': 'Bearer $token'},
  );

  if (response.statusCode == 200) {
    return User.fromJson(jsonDecode(response.body));
  } else {
    throw Exception('Failed to load user');
  }
}

Dio Framework (Production):

final dio = Dio(BaseOptions(
  baseUrl: 'https://api.example.com',
  connectTimeout: Duration(seconds: 10),
  receiveTimeout: Duration(seconds: 10),
));

// Add interceptors
dio.interceptors.add(
  InterceptorsWrapper(
    onRequest: (options, handler) async {
      options.headers['Authorization'] = 'Bearer $token';
      return handler.next(options);
    },
    onError: (error, handler) async {
      if (error.response?.statusCode == 401) {
        await _refreshToken();
      }
      return handler.next(error);
    },
  ),
);

// Use Dio
final response = await dio.get('/users/123');

2. REST API Patterns

Repository Pattern:

abstract class UserRepository {
  Future<User> getUser(String id);
  Future<List<User>> getAllUsers();
  Future<void> createUser(User user);
}

class UserRepositoryImpl implements UserRepository {
  final Dio _dio;

  UserRepositoryImpl(this._dio);

  @override
  Future<User> getUser(String id) async {
    try {
      final response = await _dio.get('/users/$id');
      return User.fromJson(response.data);
    } on DioException catch (e) {
      throw _handleError(e);
    }
  }

  @override
  Future<List<User>> getAllUsers() async {
    try {
      final response = await _dio.get('/users');
      return (response.data as List)
          .map((u) => User.fromJson(u))
          .toList();
    } on DioException catch (e) {
      throw _handleError(e);
    }
  }

  Exception _handleError(DioException e) {
    if (e.type == DioExceptionType.connectionTimeout) {
      return TimeoutException('Connection timeout');
    } else if (e.response?.statusCode == 401) {
      return UnauthorizedException('Unauthorized');
    } else if (e.response?.statusCode == 500) {
      return ServerException('Server error');
    }
    return ApiException('Unknown error');
  }
}

3. GraphQL Integration

import 'package:graphql/client.dart';

final graphQLClient = GraphQLClient(
  cache: GraphQLCache(),
  link: HttpLink('https://api.example.com/graphql'),
);

// Query
Future<User> getUser(String id) async {
  final result = await graphQLClient.query(
    QueryOptions(
      document: gql('''
        query GetUser(\$id: ID!) {
          user(id: \$id) {
            id
            name
            email
          }
        }
      '''),
      variables: {'id': id},
    ),
  );

  if (result.hasException) {
    throw Exception(result.exception);
  }

  return User.fromJson(result.data!['user']);
}

// Mutation
Future<void> updateUser(User user) async {
  final result = await graphQLClient.mutate(
    MutationOptions(
      document: gql('''
        mutation UpdateUser(\$id: ID!, \$name: String!) {
          updateUser(id: \$id, name: \$name) {
            id
            name
          }
        }
      '''),
      variables: {'id': user.id, 'name': user.name},
    ),
  );

  if (result.hasException) {
    throw Exception(result.exception);
  }
}

4. Authentication

JWT Token Management:

class AuthService {
  final Dio _dio;
  String? _accessToken;
  String? _refreshToken;

  AuthService(this._dio);

  Future<void> login(String email, String password) async {
    try {
      final response = await _dio.post('/auth/login', data: {
        'email': email,
        'password': password,
      });

      _accessToken = response.data['accessToken'];
      _refreshToken = response.data['refreshToken'];

      await _secureStorage.write(
        key: 'accessToken',
        value: _accessToken!,
      );
      await _secureStorage.write(
        key: 'refreshToken',
        value: _refreshToken!,
      );
    } on DioException catch (e) {
      throw _handleError(e);
    }
  }

  Future<String> getValidToken() async {
    if (_isTokenExpired(_accessToken)) {
      await _refreshAccessToken();
    }
    return _accessToken!;
  }

  Future<void> _refreshAccessToken() async {
    try {
      final response = await _dio.post(
        '/auth/refresh',
        data: {'refreshToken': _refreshToken},
      );

      _accessToken = response.data['accessToken'];
      await _secureStorage.write(
        key: 'accessToken',
        value: _accessToken!,
      );
    } catch (e) {
      await logout();
      rethrow;
    }
  }

  bool _isTokenExpired(String? token) {
    if (token == null) return true;
    final decoded = jwt.decode(token);
    final expiration = DateTime.fromMillisecondsSinceEpoch(
      decoded['exp'] * 1000,
    );
    return DateTime.now().isAfter(expiration);
  }

  Future<void> logout() async {
    _accessToken = null;
    _refreshToken = null;
    await _secureStorage.deleteAll();
  }
}

5. Error Handling

Custom Exceptions:

abstract class ApiException implements Exception {
  final String message;
  ApiException(this.message);
}

class NetworkException extends ApiException {
  NetworkException(String message) : super('Network Error: $message');
}

class UnauthorizedException extends ApiException {
  UnauthorizedException(String message) : super('Unauthorized: $message');
}

class ServerException extends ApiException {
  ServerException(String message) : super('Server Error: $message');
}

class ValidationException extends ApiException {
  final Map<String, String> errors;
  ValidationException(this.errors) : super('Validation Error');
}

6. Firebase Integration

import 'package:cloud_firestore/cloud_firestore.dart';

class FirebaseUserRepository {
  final firestore = FirebaseFirestore.instance;

  Future<User?> getUser(String id) async {
    try {
      final doc = await firestore.collection('users').doc(id).get();
      if (!doc.exists) return null;
      return User.fromJson(doc.data()!);
    } catch (e) {
      throw Exception('Failed to get user: $e');
    }
  }

  Stream<User?> watchUser(String id) {
    return firestore
        .collection('users')
        .doc(id)
        .snapshots()
        .map((doc) => doc.exists ? User.fromJson(doc.data()!) : null);
  }

  Future<void> updateUser(User user) async {
    await firestore.collection('users').doc(user.id).update(
      user.toJson(),
    );
  }

  Future<void> createUser(User user) async {
    await firestore.collection('users').doc(user.id).set(
      user.toJson(),
    );
  }
}

7. Retry Logic

Future<T> withRetry<T>(
  Future<T> Function() operation, {
  int maxRetries = 3,
  Duration initialDelay = const Duration(milliseconds: 100),
}) async {
  int retries = 0;
  Duration delay = initialDelay;

  while (true) {
    try {
      return await operation();
    } catch (e) {
      if (retries >= maxRetries || !_isRetryable(e)) {
        rethrow;
      }

      await Future.delayed(delay);
      delay = Duration(milliseconds: (delay.inMilliseconds * 2).toInt());
      retries++;
    }
  }
}

bool _isRetryable(dynamic error) {
  if (error is! DioException) return false;
  return error.type == DioExceptionType.connectionTimeout ||
      error.type == DioExceptionType.receiveTimeout ||
      (error.response?.statusCode ?? 0) >= 500;
}

Master backend integration for robust Flutter applications.