Agent skill

Unyo Bloc State Management

by K3vinb5 in K3vinb5/unyo-app

How to create cubits, define states, use the EffectMixin pattern, and handle side effects in the Unyo Flutter app.

BSD-3-ClauseAuto-check passedFrontend & Design

Install Unyo Bloc State Management

skills CLI
$ npx skills add K3vinb5/unyo-app --skill unyo-bloc-state-management -a claude-code

Project install by default; add -g for ~/.claude/skills/.

GitHub CLI
$ gh skill install K3vinb5/unyo-app unyo-bloc-state-management --agent claude-code

Project scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).

Manual copy
$ git clone --depth 1 https://github.com/K3vinb5/unyo-app.git skills-src && mkdir -p .claude/skills && cp -r skills-src/.agents/skills/unyo-bloc-state-management .claude/skills/unyo-bloc-state-management && rm -rf skills-src

Use ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.

Claude Code skills documentation · loads skills from .claude/skills/

Facts

Skill name
unyo-bloc-state-management
GitHub stars
664
Token cost
~3.2k tokens
SKILL.md length
768 words
Files
1
Skills in repo
7
Repo updated
First seen
Licence
BSD-3-Clause

At a glance

How to create cubits, define states, use the EffectMixin pattern, and handle side effects in the Unyo Flutter app.

  • Works in 3 steps: State — Immutable Freezed class carrying… → Cubit — Business logic that emits new… → Effect Handler — UI layer that reads…
  • Creating a new cubit
  • SKILL.md covers Architecture Overview, The Three-Part Pattern, Pattern: Defining a State and Pattern: Creating a Cubit, plus 6 more sections
  • Calls flutter

What it does

Unyo Bloc State Management is an agent skill from K3vinb5/unyo-app. How to create cubits, define states, use the EffectMixin pattern, and handle side effects in the Unyo Flutter app. Use this skill whenever creating a new cubit, defining a new state class, adding navigation/dialog/snackbar effects, handling errors in cubits, or wiring cubits to screens with BlocProvider and BlocListener. Also use when modifying existing cubit behavior or debugging state-related issues.

Its SKILL.md is about 3.2k tokens, which your agent loads only when the skill is triggered. It is a single SKILL.md file with no bundled scripts.

It sits in Frontend & Design, covering State management. It works with Flutter. The repository describes itself as: 🐙 Anime streaming and Manga reader desktop app without ads. The licence is BSD-3-Clause.

When your agent uses it

  • Creating a new cubit
  • Defining a new state class
  • Adding navigation/dialog/snackbar effects
  • Handling errors in cubits

Example prompts

  • “/unyo-bloc-state-management”

Workflow steps

3 steps, taken from the first numbered list in SKILL.md.

  1. State — Immutable Freezed class carrying all data + a list of effects
  2. Cubit — Business logic that emits new states, mixes in EffectMixin
  3. Effect Handler — UI layer that reads effects from state and executes them

What it can do on your machine

Read from SKILL.md and the folder at commit 0a44722. It shows what the files ask for, not the result of running them.

  • Tool permissions

    Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.

    From allowed-tools in the SKILL.md frontmatter.

  • Runs code

    Shell commands in SKILL.md call:

    • flutter

    From the folder's file list and the shell code blocks in SKILL.md.

  • Network

    No URLs in SKILL.md.

    From URLs in SKILL.md, links to its own repository left out.

  • Credentials

    Names no API keys, tokens, secrets or passwords.

    From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.

Context cost

Unyo Bloc State Management loads about 3.2k tokens when it runs. Until then it costs about 108 tokens; SKILL.md has 768 words of instructions outside code blocks.

Always · name and description, kept in context so the agent knows when to use it
~108
When it runs · the whole SKILL.md, loaded when a task matches
~3.2k

Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.

Safety

Auto-check passed

The automated check found no risky patterns in SKILL.md.

Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.

SKILL.md

The full file from K3vinb5/unyo-app at commit 0a44722, republished under its BSD-3-Clause licence (© K3vinb5). 768 words, ~3,205 tokens.

Download SKILL.mdSave it as .claude/skills/unyo-bloc-state-management/SKILL.md (or your agent's skills folder).
name
unyo-bloc-state-management
description
How to create cubits, define states, use the EffectMixin pattern, and handle side effects in the Unyo Flutter app. Use this skill whenever creating a new cubit, defining a new state class, adding navigation/dialog/snackbar effects, handling errors in cubits, or wiring cubits to screens with BlocProvider and BlocListener. Also use when modifying existing cubit behavior or debugging state-related issues.

Unyo BLoC State Management (Cubit + Effect Pattern)

Unyo uses Cubit (from flutter_bloc) for state management, enhanced with a custom EffectMixin that handles side effects (navigation, dialogs, snackbars) through the state itself. This is the core pattern for all business logic in the app.

Architecture Overview

lib/application/
├── cubits/
│   ├── home_cubit.dart           # Cubit classes
│   ├── anime_cubit.dart
│   ├── anime_details_cubit.dart
│   ├── video_cubit.dart
│   ├── effect_mixin.dart         # Mixin for side effects
│   └── ...
├── states/
│   ├── home_state.dart           # Freezed state classes
│   ├── anime_state.dart
│   ├── anime_details_state.dart
│   └── ...
└── effects/
    └── app_effects.dart           # Effect type definitions

The Three-Part Pattern

Every feature's state management consists of:

  1. State — Immutable Freezed class carrying all data + a list of effects
  2. Cubit — Business logic that emits new states, mixes in EffectMixin
  3. Effect Handler — UI layer that reads effects from state and executes them

Pattern: Defining a State

States are Freezed classes that implement HasEffects. Every state must include a List<AppEffect> effects field.

dart
// lib/application/states/home_state.dart
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:unyo/application/cubits/effect_mixin.dart';
import 'package:unyo/application/effects/app_effects.dart';
import 'package:unyo/core/enums/selected_menu_option.dart';
import 'package:unyo/domain/entities/anime.dart';
import 'package:unyo/domain/entities/manga.dart';
import 'package:unyo/domain/entities/user.dart';

part 'home_state.freezed.dart';

@freezed
abstract class HomeState with _$HomeState implements HasEffects {
  const factory HomeState({
    required User loggedUser,
    required SelectedMenuOption selectedMenuOption,
    required List<Anime> continueWatching,
    required List<Manga> continueReading,
    required List<String> mediaCoverImages,
    required bool isLoading,
    required bool userLoaded,
    @Default(<AppEffect>[]) List<AppEffect> effects,  // ALWAYS include this
  }) = _HomeState;

  const HomeState._();

  @override
  List<AppEffect> get stateEffects => effects;  // ALWAYS implement this
}
State conventions
  1. All fields required or have @Default() — no nullable fields in states. Use sensible defaults (empty lists, false, Model.empty()).
  2. effects always defaults to <AppEffect>[] — this is the mechanism for side effects. Without it, the UI cannot show snackbars, navigate, or open dialogs.
  3. implements HasEffects — required for EffectMixin to work.
  4. const HomeState._() — private constructor needed when you have method overrides alongside Freezed.
  5. Never have computed getters in the state — states are pure data. Put computed logic in the cubit or utility methods.
Initial state pattern

States are created with all required fields in the cubit's super() call:

dart
: super(HomeState(
    loggedUser: UserModel.empty(),
    selectedMenuOption: SelectedMenuOption.home,
    continueWatching: [],
    continueReading: [],
    mediaCoverImages: [],
    isLoading: true,
    userLoaded: false,
  ));

Use Model.empty() factory constructors for initial values, not null.

Pattern: Creating a Cubit

Cubits extend Cubit<State> and mix in EffectMixin<State>:

dart
// lib/application/cubits/home_cubit.dart
class HomeCubit extends Cubit<HomeState> with EffectMixin<HomeState> {
  // Repositories
  final UserRepositoryAnilist _userRepositoryAnilist;
  final AnimeRepositoryAnilist _animeRepositoryAnilist;
  // Notifiers
  final UserNotifier _loggedUserNotifier;
  final AnimeNotifier _selectedAnimeNotifier;
  final MangaNotifier _selectedMangaNotifier;
  final MediaListNotifier _selectedMediaListNotifier;
  final ReloadNotifier _reloadNotifier;
  // Subscriptions (for notifiers)
  late StreamSubscription<User> _newLoggedUserSubscription;
  late StreamSubscription<ReloadType> _reloadSubscription;
  // Logger
  final Logger _logger = sl<Logger>();

  HomeCubit(
    this._loggedUserNotifier,
    this._selectedAnimeNotifier,
    this._selectedMangaNotifier,
    this._selectedMediaListNotifier,
    this._userRepositoryAnilist,
    this._animeRepositoryAnilist,
    this._menuBarNotifier,
    this._reloadNotifier,
  ) : super(HomeState(
    loggedUser: UserModel.empty(),
    selectedMenuOption: SelectedMenuOption.home,
    continueWatching: [],
    continueReading: [],
    mediaCoverImages: [],
    isLoading: true,
    userLoaded: false,
  )) {
    _init();
  }

  @override
  State copyStateWithEffects(State state, List<AppEffect> effects) {
    return state.copyWith(effects: effects);
  }

  @override
  Logger get logger => _logger;

  void _init() {
    _newLoggedUserSubscription = _loggedUserNotifier.userStream.listen((user) {
      emit(state.copyWith(loggedUser: user));
      if (!state.userLoaded) {
        _getUserInfo(user);
        emit(state.copyWith(userLoaded: true, isLoading: false));
      }
    });
    _reloadSubscription = _reloadNotifier.reloadStream.listen((reloadType) async {
      if (reloadType == ReloadType.homeMediaListEntryUpdated) {
        await _getUserInfo(state.loggedUser, ignoreCacheAnime: true);
      }
    });
  }

  @override
  Future<void> close() {
    _newLoggedUserSubscription.cancel();
    _reloadSubscription.cancel();
    return super.close();
  }
}
Cubit conventions
  1. Mixin EffectMixin<State> — this is non-optional. Every cubit needs it for navigation and user feedback.
  2. Implement copyStateWithEffects() and logger — required by EffectMixin. The copyStateWithEffects implementation always uses state.copyWith(effects: effects).
  3. Constructor injection — all dependencies (repositories, notifiers) come through the constructor. The DI container provides them when creating the cubit.
  4. Private _init() method — called from constructor to set up stream subscriptions after fields are initialized.
  5. Always cancel subscriptions in close() — prevents memory leaks.

Pattern: EffectMixin — Side Effects in Cubits

The EffectMixin provides methods for navigation, dialogs, and feedback without directly accessing BuildContext (which cubits should never hold):

Available effect methods
dart
// Navigation effects
pushRouteEffect(path: "/animedetails");          // Push onto stack
replaceRouteEffect(path: "/login");               // Replace current route
navigateRouteEffect(path: "/tabs");               // Navigate within tabs
changeRouteTabEffect(context, path: "/anime");    // Switch tab in AutoTabsRouter
popRouteEffect(context);                          // Pop current route

// Dialog effects
showWidgetDialogEffect(dialog: MyDialog());                    // Show arbitrary widget dialog
showDrawerDialogEffect(
  drawerDialog: MyDrawer(),
  backgroundColor: Colors.black54,
  startPosition: AxisDirection.right,
);                                                              // Show slide-in drawer dialog
closeDialogEffect(context);                                     // Close current dialog

// Feedback effects
showSnackBarEffect("Title", message: "Details", contentType: ContentType.failure);
showSnackBarEffect("Success!", message: "Saved", contentType: ContentType.success);

// Error handling (combines logging + snackbar)
handleError("Error fetching data: $e", stackTrace: stackTrace);
How effects flow
  1. Cubit calls pushRouteEffect(path: "/animedetails")
  2. EffectMixin creates a PushRouteEffect("/animedetails") and adds it to the state's effects list via emit(copyStateWithEffects(state, [...currentEffects, effect]))
  3. BlocListener in the UI detects state.effects.isNotEmpty and calls sl<AppEffectHandler>().handleEffects(context, state.effects, cubit.clearEffects)
  4. AppEffectHandler pattern-matches on the effect type and calls AutoRouter.of(context).pushPath(...)
  5. clearEffects() removes all effects from state after processing

This pattern keeps cubits free of BuildContext while still enabling navigation and UI feedback.

Why effects instead of direct navigation?

Cubits should not hold BuildContext references (they outlive the widget tree). Effects let cubits express intent ("navigate to anime details") without knowing how or when it happens. The UI layer handles the actual navigation.

Pattern: Emitting State Changes

dart
// Simple property update
emit(state.copyWith(isLoading: true));

// Conditional logic
if (!state.userLoaded) {
  await _getUserInfo(user);
  emit(state.copyWith(userLoaded: true, isLoading: false));
}

// Error handling with effect
try {
  final data = await _repository.getData();
  emit(state.copyWith(data: data, isLoading: false));
} catch (e, stackTrace) {
  handleError("Failed to load data: $e", stackTrace: stackTrace);
  replaceRouteEffect(path: "/login");
}
Show full SKILL.md (334 more words)Show less
Key emission rules
  • Always use state.copyWith() — never mutate state directly. Freezed enforces this since all fields are immutable.
  • Chain related emissions — it's fine to emit multiple times in one method. Each emission triggers a rebuild in BlocBuilder.
  • Don't emit after async gaps without checking — after an await, the cubit might be closed. Wrap post-async logic in try/catch.

Pattern: Subscribing to Notifiers in Cubits

See the unyo-reactive-notifiers skill for the full pattern. The key steps:

  1. Declare late StreamSubscription<T> fields
  2. Subscribe in _init() called from constructor
  3. Call .cancel() on all subscriptions in close()
dart
late StreamSubscription<User> _userSub;

void _init() {
  _userSub = _userNotifier.userStream.listen((user) {
    emit(state.copyWith(loggedUser: user));
  });
}

@override
Future<void> close() {
  _userSub.cancel();
  return super.close();
}

Creating a New Cubit+State: Complete Workflow

  1. Create the state file at lib/application/states/<feature>_state.dart:

    • Freezed class implementing HasEffects
    • Include @Default(<AppEffect>[]) List<AppEffect> effects
    • All required fields with sensible defaults
    • Part directives for *.freezed.dart
  2. Create the cubit file at lib/application/cubits/<feature>_cubit.dart:

    • Extends Cubit<State> with EffectMixin<State>
    • Implements copyStateWithEffects and logger
    • Constructor injection of all dependencies
    • _init() for stream subscriptions
    • close() for cleanup
  3. Register in DI at lib/core/di/locator.dart:

    dart
    sl.registerFactory<FeatureCubit>(() => FeatureCubit(
      sl<FeatureNotifier>(),
      sl<FeatureRepositoryAnilist>(),
    ));
  4. Wire to screen — see unyo-ui-presentation skill for BlocProvider/BlocListener/BlocBuilder pattern.

  5. Run code generation:

    sh
    flutter pub run build_runner build --delete-conflicting-outputs
  6. Run analysis:

    sh
    flutter analyze

Common Pitfalls

  • Forgetting implements HasEffects: The state must implement this interface for EffectMixin to work. Without it, _currentEffects throws a StateError.
  • Not calling clearEffects() from the UI: BlocListener must call cubit.clearEffects() after processing effects, otherwise effects will keep firing on every rebuild.
  • Storing BuildContext in a cubit: Never do this. Cubits outlive widget trees. Use effects instead.
  • Mutating state directly: Freezed states are immutable. Always use state.copyWith(...).
  • Missing copyStateWithEffects implementation: Every cubit that mixes in EffectMixin must implement this. It always looks like state.copyWith(effects: effects).
  • Not canceling subscriptions: Will cause memory leaks and phantom updates on disposed cubits.
  • Registering cubits as singletons: Cubits must be registerFactory, not registerSingleton or registerLazySingleton. Each screen needs its own instance.

Cross-references

  • Effect types and handler: Examined in unyo-ui-presentation skill
  • Notifier subscription pattern: See unyo-reactive-notifiers skill
  • DI registration: See unyo-dependency-injection skill
  • State entities used in states: See unyo-domain-data-layer skill

© K3vinb5, BSD-3-Clause. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file

Files

Just SKILL.md in .agents/skills/unyo-bloc-state-management of K3vinb5/unyo-app.

Open the folder on GitHubat commit 0a44722

Compare with similar skills

Unyo Bloc State Management next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.

Unyo Bloc State Management compared with similar skills
SkillStarsUsed inTokensAuto-checkLicenceRepo updated
Unyo Bloc State Management this skillK3vinb5/unyo-app664—~3.2kAutomated safety check: PassBSD-3-Clause
Cue AnimationsMilad-Akarie/cue1191 repos~6.6kAutomated safety check: PassMIT
Flutter Riverpod State Managementandrewyng/context-hub14k—~1.1kAutomated safety check: PassMIT
BlocVeryGoodOpenSource/vgv-ai-flutter-plugin170—~2kAutomated safety check: PassMIT
Flutter Dart Code Reviewaffaan-m/ECC277k2 repos~5.8kAutomated safety check: NotesMIT
Signals for Flutterrodydavis/signals.dart819—~1.9kAutomated safety check: PassApache-2.0

Similar skills

  • Cue Animations

    Milad-Akarie/cue

    Flutter animation using the Cue package. An agent skill from Milad-Akarie/cue.

    119 GitHub starsUsed in 1 repo~6.6k tokens
    MobileAuto-check passed
  • Guides Flutter state management with Riverpod: choosing provider types, wiring ConsumerWidgets, handling async state and lifecycle, and overriding providers in tests.

    14k GitHub stars~1.1k tokensUpdated 4 mo ago
    MobileAuto-check passed
  • Bloc

    VeryGoodOpenSource/vgv-ai-flutter-plugin

    Best practices for Bloc state management in Flutter/Dart, covering Cubit versus Bloc, event and state naming, sealed classes with Equatable, the Page/View split with BlocProvider, BlocBuilder…

    170 GitHub stars~2k tokensUpdated 5 days ago
    MobileAuto-check passed
  • Library-agnostic Flutter/Dart code review checklist covering widget best practices, state management patterns (BLoC, Riverpod, Provider, GetX, MobX, Signals), Dart idioms, performance…

    277k GitHub starsUsed in 2 repos~5.8k tokens
    MobileAuto-check: notes
  • Signals for Flutter

    rodydavis/signals.dart

    Reference for the signals_flutter package: reactive signals, computed values, effects, async signals and collection signals bound to Flutter widgets.

    819 GitHub stars~1.9k tokensUpdated 27 days ago
    MobileAuto-check passed
  • Mobile Development

    rohitg00/awesome-claude-code-toolkit

    Mobile development patterns for React Native and Flutter including navigation, state management, and responsive design

    2.7k GitHub stars~1.5k tokensUpdated 5 mo ago
    MobileAuto-check passed

More from K3vinb5/unyo-app

  • Generate Dart bean classes from JSON and regenerate serialization helpers using the fjson CLI.

    664 GitHub stars~2.2k tokensUpdated 4 mo ago
    Auto-check passed
  • How to register and resolve dependencies using GetIt in the Unyo Flutter app.

    664 GitHub stars~2.4k tokensUpdated 4 mo ago
    Auto-check passed
  • Unyo Domain Data Layer

    K3vinb5/unyo-app

    How to create domain entities, data models, and repositories in the Unyo Flutter app.

    664 GitHub stars~2.9k tokensUpdated 4 mo ago
    Auto-check passed
  • Unyo Reactive Notifiers

    K3vinb5/unyo-app

    How to create and use RxDart BehaviorSubject notifiers for cross-cubit communication in the Unyo Flutter app.

    664 GitHub stars~2.8k tokensUpdated 4 mo ago
    Auto-check passed
  • Unyo Routing Navigation

    K3vinb5/unyo-app

    How to add routes, configure navigation, and use AutoRoute in the Unyo Flutter app.

    664 GitHub stars~2.5k tokensUpdated 4 mo ago
    Auto-check passed
  • Unyo UI Presentation

    K3vinb5/unyo-app

    How to build screens, widgets, and handle effects in the Unyo Flutter app's presentation layer.

    664 GitHub stars~3k tokensUpdated 4 mo ago
    Auto-check passed

Works with

Questions about Unyo Bloc State Management

What does Unyo Bloc State Management do?

How to create cubits, define states, use the EffectMixin pattern, and handle side effects in the Unyo Flutter app. Unyo Bloc State Management is an agent skill from K3vinb5/unyo-app. How to create cubits, define states, use the EffectMixin pattern, and handle side effects in the Unyo Flutter app.

When should I use Unyo Bloc State Management?

Unyo Bloc State Management fits situations like: creating a new cubit; defining a new state class; adding navigation/dialog/snackbar effects; handling errors in cubits.

How do I install Unyo Bloc State Management in Claude Code?

Run `npx skills add K3vinb5/unyo-app --skill unyo-bloc-state-management -a claude-code`. Or copy the skill folder (.agents/skills/unyo-bloc-state-management in K3vinb5/unyo-app) into .claude/skills/unyo-bloc-state-management in your project. Claude Code loads it when a task matches its description.

How do I install Unyo Bloc State Management in Codex?

Run `npx skills add K3vinb5/unyo-app --skill unyo-bloc-state-management -a codex`. Or copy the skill folder (.agents/skills/unyo-bloc-state-management in K3vinb5/unyo-app) into .agents/skills/unyo-bloc-state-management in your project. Codex loads it when a task matches its description.

Can I use Unyo Bloc State Management in Cursor, Gemini CLI or GitHub Copilot?

Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add K3vinb5/unyo-app --skill unyo-bloc-state-management -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/unyo-bloc-state-management, .gemini/skills/unyo-bloc-state-management, .github/skills/unyo-bloc-state-management and .opencode/skills/unyo-bloc-state-management in your project.

What does Unyo Bloc State Management need to run?

Going by SKILL.md and its folder, Unyo Bloc State Management needs the command-line tools its instructions call (flutter).

Does Unyo Bloc State Management access the network?

SKILL.md contains no URLs. Any network use would come from the scripts or tools the agent runs. This is read from the text; nothing was executed.

Is Unyo Bloc State Management safe to install?

Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.

What licence does Unyo Bloc State Management use?

Unyo Bloc State Management is published under the BSD-3-Clause licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.

How many tokens does Unyo Bloc State Management use?

About 3.2k tokens (SKILL.md is roughly 13k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.

What are the alternatives to Unyo Bloc State Management?

Skills that share tags, products or a category with Unyo Bloc State Management: Cue Animations (Milad-Akarie/cue, 119 stars), Flutter Riverpod State Management (andrewyng/context-hub, 14k stars), Bloc (VeryGoodOpenSource/vgv-ai-flutter-plugin, 170 stars) and Flutter Dart Code Review (affaan-m/ECC, 277k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.

Who maintains Unyo Bloc State Management?

K3vinb5 (a GitHub user) maintains it in K3vinb5/unyo-app, which has 664 GitHub stars. The repository holds 7 skills in this directory. The repository was last updated on June 12, 2026.

Source: K3vinb5/unyo-app on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.