Getting it into your agent
It runs from inside its repository, so the clone comes first — what it calls does not travel with the file alone.
git clone --depth 1 https://github.com/zakariaf/Flutter-Skillsnpx agentmods add skills/zakariaf/flutter-skills/scaffold-feature-moduleWrote this? Show the measurements
A badge with what this costs and how it scanned, read live from this page, so it follows the numbers instead of freezing them. Markdown for a README, HTML for a documentation site or a project page.
[](https://agentmods.dev/skills/zakariaf/flutter-skills/scaffold-feature-module)<a href="https://agentmods.dev/skills/zakariaf/flutter-skills/scaffold-feature-module"><img src="https://agentmods.dev/badge/skills/zakariaf/flutter-skills/scaffold-feature-module/github.svg" alt="Measured on agentmods" height="20"></a>Or the 80×15 button, for a site that already has a row of RSS and ATOM ones. Only the verdict fits; the numbers stay here.
<a href="https://agentmods.dev/skills/zakariaf/flutter-skills/scaffold-feature-module"><img src="https://agentmods.dev/badge/skills/zakariaf/flutter-skills/scaffold-feature-module.svg" alt="Reviewed on agentmods" width="80" height="20"></a>What it costs to keep this loaded
Counted locally with the o200k_base tokenizer, which is exact for GPT models; Claude uses its own tokenizer and its counts differ. Treat this as one consistent yardstick across the catalogue rather than a bill. Prices are per million input tokens.
| Model | Per session | Once invoked |
|---|---|---|
| Fable 5.1 | $0.00181 | $0.04476 |
| Opus 5 | $0.00090 | $0.02238 |
| Sonnet 5 | $0.00036 | $0.00895 |
| Haiku 4.5 | $0.00018 | $0.00448 |
Grade A, and why
scaffold-feature-module scanned grade A with 0 findings against 26 rules in 11 categories — prompt injection, anti-refusal, data exfiltration, privilege escalation, supply chain, agent snooping, system-prompt leakage, SSRF and excessive agency — measured 8d ago.
A static scan of the body, not an audit. Every finding is printed with the line that produced it so you can judge whether it matters here. A mod is markdown that instructs an agent; that is exactly why what it instructs is worth reading.
Nothing flagged
None of the 26 patterns this scan looks for appear in this file: no shell pipes, no recursive deletes, no credential paths, no hidden text, no instruction-override or anti-refusal phrasing, no agent-config snooping. That is not a guarantee, it is the absence of the things that are checkable.
How it starts
The opening of the file, as written. The whole thing — 266 lines — stays where its author put it; the contents beside it link to each section on GitHub.
Scaffold a feature module
Stand up one feature the same way every time: a folder lib/features/<feature>/ whose
presentation/ holds a dumb View, its 1:1 Notifier/AsyncNotifier ViewModel, leaf widgets/, and
scoped providers (feature-local models live in an optional domain/). A feature is a folder, not a
package. It reads shared repositories from lib/data/ and shared foundation from lib/core/, routes
every write through them, and depends only downward — never sideways into another feature.
(The single-package tree is owned by project-structure-and-packages.)
Agnostic core (holds under any state library): the View is dumb; one ViewModel per feature owns private mutable state and exposes intent methods that assign a new immutable value; reads derive from the repository (the single source of truth), writes go through one repository method (the single write path, persist-before-publish); the feature depends on abstractions and navigates by route ID. The Riverpod-first "how" below wires that with Notifiers, scoped StreamProviders, and providers-as-DI.
Read the reference for the task at hand:
references/anatomy-and-wiring.md— the fixed folder shape, the Notifier + scoped stream, watch/read/listen, family+autoDispose vs keepAlive, the single write path, and the ViewModel test.references/routing-and-l10n.md— typed go_router registration (path params, notstate.extra) and the ARB parity workflow.references/add-persisted-record.md— the optional model → table → DAO → repository chain when the feature reads a brand-new record (defers topersistence-drift).
Run scripts/scaffold_feature.sh <feature> to generate the skeleton, then scripts/verify_feature.sh before a PR.
Non-negotiable rules
- A feature is a FOLDER, never a new package.
lib/features/<feature>/,lower_snake_case, named for the screen (tasks,task_detail,settings,onboarding). A new folder is a normal addition; a new package is a deliberate boundary decision (seeproject-structure-and-packages). Do not invent numbered-folder or fixed-package-count conventions. The app package does not uselib/src/— that is a multi-package convention (seeproject-structure-and-packages). - Fixed anatomy, one primary public type per file. Under
lib/features/<feature>/presentation/:<feature>_screen.dart(the dumb View),<feature>_notifier.dart(the 1:1 Notifier/AsyncNotifier ViewModel — file name = its primary declaration, pernaming-conventions),widgets/(leaf views), and<feature>_providers.dart(providers scoped to this feature, never global). A feature-local model lives in an optionaldomain/<feature>.dart. Predictable shape = a reviewer finds any piece in one second. - The View is dumb; the ViewModel is 1:1. The View reads exactly one controller and renders —
only show/hide
ifs, layout, animation, and navigation. No repository call, notry/catchbusiness logic, no unit math or formatting inbuild(). Logic lives in the ViewModel. - A feature NEVER imports another feature. Share via a foundation layer (core/data), or navigate by route ID. Dependencies point down only — a lint/grep gate fails a cross-feature import. Sideways coupling turns two features into one un-deletable knot.
- Read the store only through repository providers; wrap
.watch()in a scoped StreamProvider. Never touch Drift, secure storage, or a platform channel from a widget or ViewModel. Scope the stream by its key (an owner/parent id, a time window) so one write never re-emits app-wide. ref.watchinbuild,ref.readin callbacks,ref.listenfor one-shot effects (SnackBar, navigate). Watching in a callback re-subscribes; reading inbuildmisses rebuilds. (Seestate-management-riverpodfor the full split.)- Per-key state is
family+autoDispose; singletons arekeepAlive. Any provider scoped to a specific entity/session isfamily-keyed on a stable equatable value andautoDisposed so it dies with its screen. Never an un-keyed "current thing" provider; neverautoDisposethe app-scope db/service singletons. - Every mutation is one repository method — the single write path, persist-before-publish. A
command on the ViewModel calls a named repository method that commits, then the stream re-emits
and the UI rebuilds. No optimistic republish, no
setState, no manual cache poke, no "save later". - Derive, don't store. Counts, totals, filtered lists, streaks are computed from the source of truth (a derived/stream provider), never a second stored counter that drifts out of sync.
- Repositories map rows → value objects; the ViewModel passes value objects. A Drift row,
companion, or
Mapnever reaches a ViewModel or widget. Measured quantities are value objects (seevalue-objects-money-and-units) — never a baredoublefor money. - Errors are typed values surfaced as
AsyncValue. Repositories return a sealedResult/Failure; the ViewModel maps it toAsyncData/AsyncError; the Viewswitches exhaustively and localizes the Failure at the presentation edge — never a raw exception string. (Seeerror-handling-typed-results.) - Register in the ONE go_router with a typed route; identity rides in path params. Add a
TypedGoRoute/GoRouteData; carry deep-linkable identity in path params (:taskId), neverstate.extra(null on cold start/OS restore). Full-screen add/edit flows setparentNavigatorKey: rootNavigatorKey. The router itself — shell/branch structure, redirect/auth guards, deep links, transitions — is owned bynavigation-and-routing; this feature only registers its route into it. - Navigate from the View or a router redirect — never from the ViewModel. The controller
publishes state; the View or a
redirectdecides what is on screen. A controller that pushes a route couples logic to navigation and breaks headless tests. - Inject "now"; never call
DateTime.now()in a feature. The ViewModel reads aClockprovider so a whole flow is assertable with a pinned fake clock. (Seeasync-safety.) - Directional geometry and localized strings only.
EdgeInsetsDirectional/AlignmentDirectional— never.left/.right,Alignment.centerLeft, orTextAlign.left. Every user-facing string comes from gen-l10n across all locale ARBs with key + placeholder parity. (Seei18n-rtl-l10n.) - Test the ViewModel by faking the repository, not the Notifier.
ProviderContainer.test()+overrideWitha fake repository andclockProvider.overrideWithValue(Clock.fixed(t)); no widget pump; verify wiring and UI-state mapping only. (Seetesting-strategy.)
What ships with it
7 files beside SKILL.md in the same directory: the scripts, references and assets a skill reads on demand. Not counted in the per-session cost; read them before you install if any of them is executable.
What this file has done since we first saw it
Hashed on every crawl. A supply-chain change to an agent config is a question of when, not whether, so the history is kept rather than the latest state alone.
- 8d ago First seen · 266 lines · 181 tokens per session scan A 0dbe986bea1a
scaffold-feature-module is a skill published in the GitHub repository zakariaf/Flutter-Skills (2 stars, last pushed 10d ago), licensed MIT. It adds 181 tokens to every session and 4,476 once invoked, about $0.0009 per session on Opus 5. A static security scan graded it A with 0 findings. No closer match exists in the catalogue, so it is treated as the original; first seen 2026-08-31.
Other skills, from other repositories
common-store-changelog
Generate user-facing release notes for the App Store and Google Play from git history (App Store <=4000 chars, Google Play <=500). Use when generating release notes, app store changelog, play store release, or "what's new" text for a mobile app.
android-navigation-3
Install and migrate to Jetpack Navigation 3. Use when implementing Navigation 3 patterns including NavDisplay, NavKey routes, deep links, multiple backstacks, scenes (dialogs, bottom sheets), or migrating from Navigation 2.
flutter-auto-route-navigation
Implement typed routing, nested routes, and auth guards using autoroute in Flutter. Use when the task explicitly uses autoroute or its generated router; defer generic deep-link setup and other routing libraries.
flutter-dependency-injection
Configure service locator setup using injectable and getit in Flutter. Use when wiring dependency injection with getit or injectable.
flutter-getx-state-management
Implement reactive state with GetX controllers, bindings, and observables in Flutter. Use when managing app state with GetxController, Obx, GetBuilder, or dependency lifecycle—not unit tests for existing controllers.
quality-engineering-appium-mcp
Drives iOS/Android mobile devices via Appium MCP. Use for verifying mobile bugs, E2E tests, and navigating real device clouds (LambdaTest/BrowserStack).