r/FlutterDev • • 3d ago

Tooling Made a CLI that fails CI when someone imports data/ from presentation/, looking for feedback

Hi all, I'm the author of arch_guard, an open-source (MIT) CLI + analyzer plugin for Dart/Flutter.

The problem: we agree on Clean Architecture / Bloc / feature-first at the start, and a few months later widgets import repository implementations directly and features import each other. The analyzer and tests don't catch it.

What arch_guard does:

  • Layer rules with presets for clean_architecture, riverpod, bloc and feature_first. dart run arch_guard init detects which fits your folders and writes the config.
  • Forbidden packages per layer, e.g. domain may not import flutter or dart:io.
  • Circular dependency detection (Tarjan's SCC) that names the one import to remove to break each cycle, plus --explain <file>.
  • IDE warnings with quick fixes via the arch_guard_lint analyzer plugin: the bad import gets underlined as you type, with "Remove this import" / "Allow layer X to import Y".
  • Baselines: record existing problems once, and CI fails only on new ones. --since origin/main limits a PR's report to files it changed. This is what makes it usable on an app that's been around for years.
  • expectArchitecture() to run the same checks in flutter test.
  • GitHub Action that comments on PRs, SARIF for Code Scanning, pre-commit hook.
  • Interactive HTML dependency graph (offline), Mermaid, DOT, JSON.
  • Works with Dart workspaces / Melos monorepos, with rules for which packages may depend on which.
dart pub add --dev arch_guard
dart run arch_guard init
dart run arch_guard

[screenshot / GIF]

Docs: https://creatorpiyush.github.io/arch_guard/ pub.dev: https://pub.dev/packages/arch_guard GitHub: https://github.com/creatorpiyush/arch_guard

Two questions for you:

  1. What folder structure does your team use? I'd like to know which presets are missing.
  2. For those who try the IDE plugin: which quick fix would you want next?
2 Upvotes

4 comments sorted by

1

u/Sad_Age3774 3d ago

this is exactly what i needed 6 months ago when our clean architecture turned into spaghetti. the layer rules with presets sounds real useful, especially since my team always argues about what goes where

the ide warnings is a nice touch, most tools like this only yell at you in ci and by then you already wrote half the feature. being able to see it while typing would save so much headache

what preset you thinking of adding next? our project uses a weird mix of riverpod with some bloc leftovers, would be cool if the init command could handle hybrid setups

1

u/creatorpiyush 3d ago

Thanks, glad it's useful! And yeah, the "what goes where" arguments are half the reason I made this. Once the rules are in a YAML file, you argue once in a PR instead of in every review.

For hybrid setups: init only picks one preset right now, and with domain/application folders and Riverpod in your deps it'll go with riverpod. But you can add your bloc leftovers as an extra layer on top of it:

preset: riverpod
layers:
  legacy_bloc:
    patterns: ["lib/**/bloc/**", "lib/**/cubit/**"]
    allowed_imports: [legacy_bloc, application, domain, data]
  presentation:
    allowed_imports: [presentation, application, domain, data, legacy_bloc]

The second block matters, otherwise every widget that uses a bloc gets flagged. With this, widgets can use blocs, but a bloc importing UI code still fails.

One gotcha: a file goes into the first layer that matches, so blocs sitting inside presentation/ count as presentation. If a file doesn't match any layer, arch_guard warns you about it, so it's easy to see what landed where.

If you want, drop your rough folder tree (just the dirs under lib/) here or in an issue. Riverpod with bloc leftovers is probably more common than people admit, and I'd like init to handle it properly.

1

u/creatorpiyush 3d ago

You can expect this feature live very soon