A

Advisor Flutter Go Reviewer

A agent template for development tools workflows. Streamlines development with pre-configured patterns and best practices.

AgentClipticsdevelopment toolsv1.0.0MIT
0 views0 copies

Advisor Flutter Go Reviewer

A specialized code review agent for full-stack projects using Flutter (Dart) for the frontend and Go (Golang) for the backend, providing thorough reviews covering Riverpod/GetX state management, Protobuf APIs, and PostgreSQL interactions.

When to Use This Agent

Choose Advisor Flutter Go Reviewer when:

  • Reviewing pull requests in Flutter + Go full-stack projects
  • Checking Protobuf schema changes and gRPC service definitions
  • Validating Riverpod or GetX state management patterns in Flutter
  • Reviewing PostgreSQL queries and migrations in Go services
  • Ensuring consistency between frontend API calls and backend endpoints

Consider alternatives when:

  • Reviewing pure web frontend projects (use a general code reviewer)
  • Working on Go microservices without a Flutter frontend (use a Go-specific reviewer)
  • Designing system architecture (use an architecture reviewer agent)

Quick Start

# .claude/agents/advisor-flutter-go-reviewer.yml name: Advisor Flutter Go Reviewer description: Review Flutter + Go full-stack code model: claude-sonnet tools: - Read - Glob - Grep - Bash

Example invocation:

claude "Review the changes in the feature/user-profile branch, checking both the Flutter UI and Go backend for consistency, error handling, and best practices"

Core Concepts

Review Framework

LayerFocus AreasCritical Checks
Flutter UIWidget composition, state managementRiverpod provider lifecycle, widget rebuilds
Dart LogicBusiness logic, modelsNull safety, freezed/json_serializable correctness
ProtobufAPI contractsBreaking changes, field numbering, naming
Go HandlersHTTP/gRPC handlersInput validation, error codes, auth middleware
Go ServicesBusiness logicTransaction boundaries, error wrapping
PostgreSQLQueries and migrationsIndex usage, migration reversibility, N+1 queries

Flutter Review Checklist

// Riverpod provider review points // 1. Provider type matches lifecycle needs final userProvider = FutureProvider.autoDispose .family<User, String>((ref, userId) async { // autoDispose: cleaned up when no longer listened to // family: parameterized by userId final api = ref.watch(apiClientProvider); return api.getUser(userId); }); // 2. Widget rebuild scope is minimal class UserProfile extends ConsumerWidget { Widget build(BuildContext context, WidgetRef ref) { // Watch only what this widget needs final userName = ref.watch( userProvider(userId).select((user) => user.name), ); return Text(userName); } } // 3. Error handling is user-visible final userState = ref.watch(userProvider(userId)); return userState.when( data: (user) => UserCard(user: user), loading: () => const UserCardSkeleton(), error: (err, stack) => ErrorDisplay( message: 'Could not load profile', onRetry: () => ref.invalidate(userProvider(userId)), ), );

Go Backend Review Checklist

// Handler review points func (h *UserHandler) GetUser(ctx context.Context, req *pb.GetUserRequest) (*pb.GetUserResponse, error) { // 1. Input validation if req.UserId == "" { return nil, status.Error(codes.InvalidArgument, "user_id is required") } // 2. Authorization check callerID, err := auth.ExtractUserID(ctx) if err != nil { return nil, status.Error(codes.Unauthenticated, "invalid credentials") } // 3. Business logic delegation user, err := h.userService.GetByID(ctx, req.UserId) if err != nil { // 4. Error wrapping with context if errors.Is(err, service.ErrNotFound) { return nil, status.Error(codes.NotFound, "user not found") } return nil, status.Error(codes.Internal, "failed to fetch user") } // 5. Response mapping return &pb.GetUserResponse{ User: toProtoUser(user), }, nil }

Configuration

ParameterDescriptionDefault
flutter_stateState management library (riverpod, getx, bloc)riverpod
go_frameworkGo HTTP/gRPC framework (stdlib, gin, echo, grpc)grpc
api_formatAPI contract format (protobuf, openapi, graphql)protobuf
db_toolDatabase access (sqlx, gorm, pgx, sqlc)sqlx
review_depthReview thoroughness (quick, standard, deep)standard
check_consistencyVerify frontend-backend API contract alignmenttrue

Best Practices

  1. Verify that Protobuf field numbers are never reused or changed. In Protobuf, field numbers are the wire format identity. Changing a field number is a breaking change that silently corrupts data. When reviewing proto file changes, verify that only new fields are added (with new numbers), deprecated fields are marked reserved, and existing field numbers and types are unchanged. This is the single most critical review check for Protobuf APIs.

  2. Check that Flutter widgets watch only the state they render. A widget that watches an entire user object re-renders when any field changes, even fields it does not display. Use .select() to watch specific fields: ref.watch(userProvider.select((u) => u.name)). This reduces unnecessary rebuilds and improves UI performance. Every ref.watch() call in a review should be checked for over-subscription.

  3. Validate Go error handling wraps context at every layer. A raw return err from a database call produces unhelpful error messages like "sql: no rows." Each layer should wrap errors with context: fmt.Errorf("getting user %s: %w", userID, err). This produces error chains like "handling GetUser: getting user abc123: sql: no rows" that pinpoint both what failed and where in the call chain it failed.

  4. Check PostgreSQL queries for index usage and N+1 patterns. In Go code, verify that WHERE clauses filter on indexed columns. Look for patterns where a query runs inside a loop (N+1). In Flutter, check that list screens do not trigger individual API calls per item. Suggest batch endpoints or JOIN queries when N+1 patterns are found. A single query returning 100 rows is always better than 100 queries returning 1 row each.

  5. Ensure error handling in Flutter shows user-actionable messages. Raw error messages from the backend ("INTERNAL: failed to fetch user") should never reach the UI. Map gRPC status codes to user-friendly messages in a centralized error handler. Include retry actions for transient errors (network timeouts) and help links for persistent errors (account issues). The .when(error:) callback should always show something the user can act on.

Common Issues

Protobuf generated code is out of sync with proto definitions. Developers modify .proto files but forget to regenerate Dart and Go code. The build succeeds because the old generated code still compiles, but runtime behavior is incorrect. Add a CI step that regenerates all Protobuf code and fails if the generated output differs from what is committed. This catches missing regeneration before merge.

Riverpod provider dependencies create circular references or memory leaks. Providers that watch each other can create cycles that prevent disposal, leaking memory. Review provider dependency chains for circularity. Use autoDispose on providers that are not needed globally. Check that ref.listen callbacks are cleaned up and that ref.keepAlive() is used sparingly and intentionally.

Go database transactions are not properly committed or rolled back. Missing defer tx.Rollback() calls after db.Begin() leave open transactions that exhaust connection pools. Review all transaction usage to verify that every Begin() has a corresponding Commit() on success and Rollback() on failure, typically via defer. Use a helper function that wraps the transaction lifecycle to prevent this class of bug entirely.

Community

Reviews

Write a review

No reviews yet. Be the first to review this template!

Similar Templates