All skills
jeffallan avatar

/flutter-expert

@efebc44
by jeffallanjeffallan/claude-skills12k stars
1,124

Use when building cross-platform applications with Flutter 3+ and Dart. Invoke for widget development, Riverpod/Bloc state management, GoRouter navigation, platform-specific implementations, performance optimization.

Use this Skill: https://skilld.dev/gh/jeffallan/claude-skills/flutter-expert

This session only. Nothing lands on disk.

referencesbloc-state.md

≈1.2k tokens on demand. Your agent reads this file only when SKILL.md points to it.

Bloc State Management

When to Use Bloc

Use Bloc/Cubit when you need:

  • Explicit event → state transitions
  • Complex business logic
  • Predictable, testable flows
  • Clear separation between UI and logic
Use Case Recommended
Simple mutable state Riverpod
Event-driven workflows Bloc
Forms, auth, wizards Bloc
Feature modules Bloc

Core Concepts

Concept Description
Event User/system input
State Immutable UI state
Bloc Event → State mapper
Cubit State-only (no events)

Basic Bloc Setup

Event

sealed class CounterEvent {}

final class CounterIncremented extends CounterEvent {}

final class CounterDecremented extends CounterEvent {}

State

class CounterState {
  final int value;

  const CounterState({required this.value});

  CounterState copyWith({int? value}) {
    return CounterState(value: value ?? this.value);
  }
}

Bloc

import 'package:flutter_bloc/flutter_bloc.dart';

class CounterBloc extends Bloc<CounterEvent, CounterState> {
  CounterBloc() : super(const CounterState(value: 0)) {
    on<CounterIncremented>((event, emit) {
      emit(state.copyWith(value: state.value + 1));
    });

    on<CounterDecremented>((event, emit) {
      emit(state.copyWith(value: state.value - 1));
    });
  }
}

Cubit (Recommended for Simpler Logic)

class CounterCubit extends Cubit<int> {
  CounterCubit() : super(0);

  void increment() => emit(state + 1);
  void decrement() => emit(state - 1);
}

Providing Bloc to the Widget Tree

BlocProvider(
  create: (_) => CounterBloc(),
  child: const CounterScreen(),
);

Multiple blocs:

MultiBlocProvider(
  providers: [
    BlocProvider(create: (_) => AuthBloc()),
    BlocProvider(create: (_) => ProfileBloc()),
  ],
  child: const AppRoot(),
);

Using Bloc in Widgets

BlocBuilder (UI rebuilds)

class CounterScreen extends StatelessWidget {
  const CounterScreen({super.key});

  @override
  Widget build(BuildContext context) {
    return BlocBuilder<CounterBloc, CounterState>(
      buildWhen: (prev, curr) => prev.value != curr.value,
      builder: (context, state) {
        return Text(
          state.value.toString(),
          style: Theme.of(context).textTheme.displayLarge,
        );
      },
    );
  }
}

BlocListener (Side Effects)

BlocListener<AuthBloc, AuthState>(
  listenWhen: (prev, curr) => curr is AuthFailure,
  listener: (context, state) {
    if (state is AuthFailure) {
      ScaffoldMessenger.of(context)
          .showSnackBar(SnackBar(content: Text(state.message)));
    }
  },
  child: const LoginForm(),
);

BlocConsumer (Builder + Listener)

BlocConsumer<FormBloc, FormState>(
  listener: (context, state) {
    if (state.status == FormStatus.success) {
      context.pop();
    }
  },
  builder: (context, state) {
    return ElevatedButton(
      onPressed: state.isValid
          ? () => context.read<FormBloc>().add(FormSubmitted())
          : null,
      child: const Text('Submit'),
    );
  },
);

Accessing Bloc Without Rebuilds

context.read<CounterBloc>().add(CounterIncremented());

⚠️ Never use watch inside callbacks


Async Bloc Pattern (API Calls)

on<UserRequested>((event, emit) async {
  emit(const UserState.loading());

  try {
    final user = await repository.fetchUser();
    emit(UserState.success(user));
  } catch (e) {
    emit(UserState.failure(e.toString()));
  }
});

Bloc + GoRouter (Auth Guard Example)

redirect: (context, state) {
  final authState = context.read<AuthBloc>().state;

  if (authState is Unauthenticated) {
    return '/login';
  }
  return null;
}

Testing Bloc

blocTest<CounterBloc, CounterState>(
  'emits incremented value',
  build: () => CounterBloc(),
  act: (bloc) => bloc.add(CounterIncremented()),
  expect: () => [
    const CounterState(value: 1),
  ],
);

Best Practices (MUST FOLLOW)

✅ Immutable states ✅ Small, focused blocs ✅ One feature = one bloc ✅ Use Cubit when possible ✅ Test all blocs

❌ No UI logic inside blocs ❌ No context usage inside blocs ❌ No mutable state ❌ No massive “god blocs”


Quick Reference

Widget Purpose
BlocBuilder UI rebuild
BlocListener Side effects
BlocConsumer Both
BlocProvider Dependency injection
MultiBlocProvider Multiple blocs

Source: SKILL.md on GitHub

1 alert17d5 checks · Risk CRITICAL
  • Gen Agent Trust Hub17d

    The skill is a legitimate development guide for Flutter and Dart applications. It contains standard coding patterns, configuration guides, and architecture references. The URL flagged by automated scans belongs to the verified author's own repository infrastructure and presents no security risk.

  • Socket17d

    No alerts

  • Snyk17d

    Risk: LOW · No issues

  • Runlayer6mo

    7 files scanned · No issues

  • ZeroLeaks5mo

    Score: 93/100 · 2 sections analyzed

Signed by skilld at efebc44. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub 2 months ago.

Steadyupdated 5 months ago
Other metadata
metadata
{
  "author": "https://github.com/Jeffallan",
  "version": "1.1.0",
  "domain": "frontend",
  "triggers": "Flutter, Dart, widget, Riverpod, Bloc, GoRouter, cross-platform",
  "role": "specialist",
  "scope": "implementation",
  "output-format": "code",
  "related-skills": "react-native-expert, test-master, fullstack-guardian"
}
  • flutter
  • dart
  • riverpod
  • bloc
  • gorouter
  • widget
  • state-management
  • cross-platform
  • mobile

README badge

README badge for jeffallan/claude-skills/flutter-expert

Provides patterns and workflow for building cross-platform Flutter apps with Dart, covering Riverpod or Bloc state management, GoRouter navigation, widget optimization, and performance profiling. Use this skill when implementing Flutter 3+ features, custom widgets, or debugging jank and rebuild issues.

Generated from the current SKILL.md.

Does this skill support both Riverpod and Bloc state management?
Yes. The skill covers both Riverpod (with StateNotifierProvider and ConsumerWidget) and Bloc/Cubit patterns. Load the appropriate reference guide based on your state management choice.
What versions of Flutter and Dart does this cover?
Flutter 3+ and Dart. The skill assumes a modern Flutter setup and uses current patterns like const constructors and DevTools profiling.
Does this skill include platform-specific iOS and Android implementations?
Yes. The skill covers platform-specific implementations as part of its core workflow, though detailed guidance is loaded from the performance and project structure references.
Can this skill help with performance optimization and jank fixes?
Yes. The skill includes a dedicated optimization workflow that uses Flutter DevTools profiling, identifies expensive build calls, and applies fixes like RepaintBoundary and const constructors.
Does this skill provide testing guidance?
Yes. Widget and integration testing with flutter_test is part of the core workflow, including test coverage tracking and targeted test additions when coverage drops.

Generated from the current SKILL.md. These answers refresh after source changes.