flutter-skeletonizer-engineering
Skill8 starsChanged 48 days agoMITView on GitHub
Design, implement, review, debug, test, profile, and migrate production Flutter skeleton-loading UX using skeletonizer. Use this skill whenever work involves Skeletonizer, SliverSkeletonizer, Skeletonizer.zone, Bone widgets, shimmer/pulse/solid effects, loading placeholders, fake-data skeletons, annotation choice, loading-state UX, skeletonized lists or grids, accessibility of placeholders, reduced motion, heavy images/charts/platform views during loading, pagination/refresh skeletons, or performance issues caused by skeleton rendering—even when the user only reports layout shift, fake controls being tappable, screen readers reading placeholder text, or shimmer jank.
In this repository70 other files it gives its agents.
- camerawesome-flutterSkill
- dart-args-production-cliSkill
- dart-flutter-equatable-engineeringSkill
- dart-flutter-ffi-systems-engineeringSkill
- dart-metaSkill
- document-camera-frameSkill
- document-scan-flutterSkill
- figma-to-flutter-expertSkill
- flutter-animations-production-engineeringSkill
- flutter-app-hardening-reverse-engineeringSkill
- flutter-app-icon-engineeringSkill
- flutter-application-security-engineeringSkill
- flutter-app-links-deep-link-engineeringSkill
- flutter-cachingSkill
- flutter-concurrency-memory-performanceSkill
- flutter-confetti-engineeringSkill
- flutter-dart-package-engineeringSkill
- flutter-design-system-from-design-mdSkill
- flutter-dio-cache-interceptor-engineeringSkill
- flutter-dio-engineeringSkill
- flutter-doc-scannerSkill
- flutter-drift-persistence-engineeringSkill
- flutter-expert-tipsSkill
- flutter-firebase-analyticsSkill
- flutter-firebase-core-engineeringSkill
- flutter-firebase-messagingSkill
- flutter-get-it-injectable-dependency-injectionSkill
- flutter-go-router-engineeringSkill
- flutter-hive-persistence-engineeringSkill
- flutter-image-performanceSkill
- flutter-image-picker-production-engineeringSkill
- flutter-lints-static-analysis-engineeringSkill
- flutter-local-notifications-production-engineeringSkill
- flutter-memory-leak-engineeringSkill
- flutter-mobile-developmentSkill
- flutter-motion-engineeringSkill
- flutter-multi-environmentSkill
- flutter-native-splash-engineeringSkill
- flutter-package-plugin-selectionSkill
- flutter-path-provider-production-storageSkill
- flutter-performance-jank-optimizationSkill
- flutter-permission-handler-engineeringSkill
- flutter-pinputSkill
- flutter-production-build-releaseSkill
- flutter-production-engineeringSkill
- flutter-production-loggingSkill
- flutter-pro-image-editor-engineeringSkill
- flutter-secure-storage-security-engineeringSkill
- flutter-sentry-engineeringSkill
- flutter-share-plus-engineeringSkill
- flutter-squadron-concurrency-engineeringSkill
- flutter-supabase-engineeringSkill
- flutter-svg-engineeringSkill
- flutter-ui-performance-engineeringSkill
- flutter-url-launcher-engineeringSkill
- flutter-video-player-production-engineeringSkill
- flutter-webview-production-engineeringSkill
- freezed-production-engineeringSkill
- html-to-flutterSkill
- hydrated-blocSkill
- The first 60 shown.
The file
Show its rules and text
We split this skill into the rules it gives an agent
56 rules. About 0 are common, 41 are distinctive, and 15 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈41
Distinctive · estimate
This author's own choices. Worth a look.
15
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 12
Use this governing model:
- Distinctive: line 30
Prefer skeletons for predictable initial or unresolved section layouts.
- Distinctive: line 31
Keep loaded content visible during refresh.
- Distinctive: line 32
Keep loaded rows visible during pagination.
- Distinctive: line 33
Use targeted progress/disabled states for mutations.
- Distinctive: line 34
Use determinate progress when real progress exists.
- Distinctive: line 35
Use an empty state only after a successful empty result.
- Distinctive: line 36
Keep fake values out of repositories, domain entities, persistence, analytics, and actions.
- Distinctive: line 38
Do not assume Skeletonizer invents layout.
- Distinctive: line 39
Do not assume skeleton paint prevents child construction, resource initialization, network image fetches, chart work, or platform-view …
- Very specific: line 40
Use Skeleton.replace or conditional construction when expensive descendants should not exist during loading.
- Very specific: line 41
Start with ignorePointers: true for fake initial content.
- Distinctive: line 42
If scrolling requires pointer handling, protect fake controls locally and ensure callbacks cannot act on placeholders.
- Distinctive: line 43
Treat pointer safety and semantics safety separately.
- Distinctive: line 45
Keep meaningful navigation controls outside the excluded skeleton subtree when they must remain usable.
- Distinctive: line 47
Use light/dark theme-aware skeleton configuration.
- Distinctive: line 49
Do not keep shimmer running after failure.
- Distinctive: line 50
Do not use skeletons as a substitute for caching.
- Very specific: line 51
Do not add RepaintBoundary mechanically.
- Distinctive: line 53
Use only APIs verified for the installed Skeletonizer version.
- Distinctive: line 56
Read only the reference needed for the task:
- Distinctive: line 66
Before editing code, determine:
- Distinctive: line 104
Do not start by replacing widgets.
- Distinctive: line 107
Use distinct states such as:
- Very specific: line 117
Do not overload one isLoading when UX differs.
- Very specific: line 164
Never make repositories emit fake users/products/orders just to shape skeletons.
- Very specific: line 172
If automatic mode needs strings to shape text, use deterministic presentation-only placeholders or BoneMock.
- Distinctive: line 205
Use this decision table:
- Very specific: line 222
Use replace rather than leaf when the goal is to avoid expensive initialization.
- Distinctive: line 250
Do not fetch or decode production media only so its pixels can be covered by a skeleton.
- Very specific: line 272
Never eagerly build hundreds of fake rows.
- Distinctive: line 285
If users must scroll the skeletonized subtree and pointer blocking must be disabled:
- Distinctive: line 288
ensure callbacks cannot receive placeholder entities.
- Very specific: line 290
Prefer keeping real back/close/navigation chrome outside the skeleton subtree.
- Distinctive: line 293
Do not assume hidden/shimmered content disappears from the semantics tree.
- Very specific: line 308
Do not use Skeleton.ignore as a semantics mechanism.
- Distinctive: line 311
Use application-level Skeletonizer configuration for consistent effects.
- Very specific: line 321
Do not hardcode one light shimmer palette into dark mode.
- Distinctive: line 336
Keep these package types out of repositories/domain code:
- Distinctive: line 345
Use selectors/build filters so unrelated state changes do not rebuild giant animated skeleton subtrees.
- Very specific: line 355
Never infer loading from data == null if null also represents failure.
- Very specific: line 359
Use SolidColorEffect when animation is irrelevant to the test.
- Distinctive: line 376
Use profile mode and representative physical hardware.
- Distinctive: line 388
If skeleton state is more janky than loaded content, optimize in this order:
- Distinctive: line 392
stop unnecessary image/network work.
- Very specific: line 393
remove costly shade/nested skeleton scopes.
- Distinctive: line 396
only then test targeted repaint boundaries.
- Distinctive: line 397
Keep only improvements supported by measurement.
- Distinctive: line 402
read intervening changelog entries.
- Distinctive: line 403
search all Skeletonizer APIs.
- Distinctive: line 406
test annotations and custom effects.
- Very specific: line 407
run widget/accessibility/golden tests.
- Distinctive: line 421
Do not copy current-baseline APIs into an older locked project without verification.
- Distinctive: line 424
When reviewing existing code, report findings in this order:
- Distinctive: line 456
Before adding or changing Skeletonizer code, answer:
- Distinctive: line 474
Use Skeletonizer as a presentation painting tool, not as a substitute for state modeling, caching, progress reporting, accessibility, or …
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Flutter Skeletonizer Engineering
Mission
Build skeleton loading that improves perceived responsiveness without corrupting state semantics, accessibility, interaction safety, layout stability, or frame performance. Use this governing model:
user operation
→ classify loading phase
→ decide whether skeleton is appropriate
→ preserve final geometry
→ keep fake data presentation-only
→ suppress unsafe interaction + fake semantics
→ replace/defer expensive descendants
→ choose theme/motion-aware effect
→ test loading transitions
→ profile on representative hardwareA shimmer is not a loading architecture.
Non-negotiable rules
- Classify the operation before choosing a skeleton.
- Prefer skeletons for predictable initial or unresolved section layouts.
- Keep loaded content visible during refresh.
- Keep loaded rows visible during pagination.
- Use targeted progress/disabled states for mutations.
- Use determinate progress when real progress exists.
- Use an empty state only after a successful empty result.
- Keep fake values out of repositories, domain entities, persistence, analytics, and actions.
- Preserve final geometry: constraints, line counts, spacing, aspect ratios, and responsive behavior.
- Do not assume Skeletonizer invents layout; it transforms the paint of an already-shaped tree.
- Do not assume skeleton paint prevents child construction, resource initialization, network image fetches, chart work, or platform-view startup.
- Use
Skeleton.replaceor conditional construction when expensive descendants should not exist during loading. - Start with
ignorePointers: truefor fake initial content. - If scrolling requires pointer handling, protect fake controls locally and ensure callbacks cannot act on placeholders.
- Treat pointer safety and semantics safety separately.
- Exclude placeholder semantics explicitly; expose one useful loading status where appropriate.
- Keep meaningful navigation controls outside the excluded skeleton subtree when they must remain usable.
- Honor reduced-motion preferences; use a non-animated treatment when requested.
- Use light/dark theme-aware skeleton configuration.
- Bound placeholder count around the viewport and build lists/grids lazily.
- Do not keep shimmer running after failure.
- Do not use skeletons as a substitute for caching.
- Do not add
RepaintBoundarymechanically. - Profile large animated skeletons in profile mode on representative physical hardware.
- Use only APIs verified for the installed Skeletonizer version.
Reference routing
Read only the reference needed for the task:
| Need | Read |
| Decide skeleton vs spinner/cached content, understand package mechanics, fake-data boundaries, sizing/layout | references/01-foundations-loading-model.md |
Choose ignore/keep/replace/leaf/unite/shade, handle text/images/buttons/lists/grids/pagination/slivers | references/02-annotations-components-lists.md |
| Configure effects, reduced motion, themes, accessibility, hit testing, state management, design-system wrappers, performance | references/03-effects-accessibility-performance.md |
| Handle maps/WebViews/charts/forms/tables, responsive/localized layouts, testing, debugging, upgrades | references/04-heavy-widgets-testing-migration.md |
| Review anti-patterns, implementation/refactor workflows, checklists, and production gate | references/05-antipatterns-workflows-checklists.md |
Step 1 — Inspect the repository
Before editing code, determine:
Flutter version
Dart version
skeletonizer version + lockfile
state-management model
current loading-state model
current skeleton APIs/annotations
theme configuration
responsive layout logic
image/SVG/chart/platform-view usage
accessibility conventions
tests/goldens
performance evidenceSearch for:
Skeletonizer(
Skeletonizer.zone
Skeletonizer.sliver
SliverSkeletonizer
Bone.
Skeleton.ignore
Skeleton.keep
Skeleton.replace
Skeleton.leaf
Skeleton.unite
Skeleton.shade
Skeleton.ignorePointer
ShimmerEffect
PulseEffect
SolidColorEffect
isLoading
isRefreshing
loadingMoreDo not start by replacing widgets. First map loading semantics.
Step 2 — Classify the loading state
Use distinct states such as:
initialLoading
loaded
refreshing
loadingMore
mutationInProgress
failureDo not overload one isLoading when UX differs.
Choose UX:
| Situation | Default |
| Predictable first content load | Skeleton |
| Predictable unresolved section | Local skeleton |
| Unknown final structure | Spinner/neutral loading |
| Useful cached/stale content exists | Keep content + refresh affordance |
| Pull-to-refresh | Keep content + refresh indicator |
| Pagination | Keep rows + append placeholders/footer |
| Upload/download with progress | Determinate progress |
| Local save/toggle/like | Targeted disabled/progress state |
| Successful empty result | Empty state |
| Auth/bootstrap destination unknown | Branded/neutral bootstrap |
| One image unresolved | Image-local placeholder |
| Reject skeleton loading if it would misrepresent unknown structure or flash too briefly to help. |
Step 3 — Understand the package model
Automatic mode needs a shaped widget tree:
Skeletonizer(
enabled: state.isInitialLoading,
child: content,
)The real/fake presentation layout still participates in build and layout. Skeletonizer changes painting for eligible descendants. Manual mode defines geometry explicitly:
Skeletonizer.zone(
child: const Column(
children: [
Bone.text(words: 3),
Bone.multiText(lines: 2),
],
),
)Choose automatic mode when reusing the final layout minimizes drift and the subtree is safe to construct. Choose zone/manual Bones when:
- fake domain graphs would be elaborate;
- expensive descendants should not be built;
- real widgets cannot exist before data arrives;
- a simpler intentional placeholder is clearer.
Step 4 — Keep fake data presentation-only
Never make repositories emit fake users/products/orders just to shape skeletons. Preferred flow:
real repository state
→ presentation maps loading to placeholder view models/Bones
→ skeleton UIIf automatic mode needs strings to shape text, use deterministic presentation-only placeholders or BoneMock. No placeholder value may drive:
- navigation;
- analytics;
- persistence;
- authorization;
- cart/checkout actions;
- API requests.
Step 5 — Match final geometry
Preserve:
card/row bounds
avatar/image dimensions
aspect ratios
border radii
padding/gaps
grid columns
title/subtitle line counts
button positions/heights
table column widths
responsive breakpointsFor text, keep the same production Text constraints and plausible wrapping. Skeletonizer derives text bones from laid-out paragraph metrics.
Test with:
- short/typical/long content;
- localization;
- RTL;
- large text scaling;
- phone/tablet/desktop constraints. Skeleton paint cannot fix bad placeholder geometry.
Step 6 — Choose annotations by intent
Use this decision table:
| Intent | API |
| Hide paint during skeleton mode | Skeleton.ignore |
| Keep child painted normally | Skeleton.keep |
| Build a lightweight substitute instead of real child | Skeleton.replace |
| Treat a compound subtree as one bone-like region | Skeleton.leaf |
| Merge nearby small painted shapes | Skeleton.unite |
| Shader-shade custom-painted output | Skeleton.shade |
| Disable interaction for a local subtree | Skeleton.ignorePointer |
| Important distinctions: |
ignore ≠ keep
leaf ≠ replace
pointer blocking ≠ semantics exclusionUse replace rather than leaf when the goal is to avoid expensive initialization.
Step 7 — Audit expensive descendants
Explicitly inspect:
Image.network / high-resolution images
SVG/vector renderers
charts
CustomPainter
maps
WebViews
camera/video previews
platform views
animationsDefault strategy:
expensive real widget
→ do not build while loading
→ lightweight Bone/replacement with same geometryExamples:
- image →
Skeleton.replacewith circle/rectangle; - complex chart → chart-area
Bone; - map/WebView/camera → fixed-size replacement;
- custom painter →
shadeonly when visually useful and measured. Do not fetch or decode production media only so its pixels can be covered by a skeleton.
Step 8 — Lists, grids, refresh, pagination
Initial load:
no useful content
→ lazy viewport-sized skeleton list/gridPagination:
loaded items
+ 2–4 bottom skeleton rows/cardsRefresh:
loaded content
+ refresh affordanceShare the production list/grid delegate and responsive breakpoint logic.
Never eagerly build hundreds of fake rows.
For sliver layouts, preserve sliver architecture with Skeletonizer.sliver / SliverSkeletonizer. Do not convert a sliver screen to an eager Column for loading.
Step 9 — Interaction safety
Default:
Skeletonizer(
enabled: loading,
ignorePointers: true,
child: content,
)If users must scroll the skeletonized subtree and pointer blocking must be disabled:
- enable pointer interaction deliberately;
- wrap buttons/links/fake controls with
Skeleton.ignorePointer; - ensure callbacks cannot receive placeholder entities;
- test gestures. Prefer keeping real back/close/navigation chrome outside the skeleton subtree.
Step 10 — Accessibility
Do not assume hidden/shimmered content disappears from the semantics tree. For fake placeholder content:
Semantics(load status)
→ ExcludeSemantics(placeholder subtree)
→ SkeletonizerRequirements:
- placeholder names/prices/addresses are not announced;
- fake controls expose no meaningful actions;
- one useful loading announcement exists only where warranted;
- back/close controls remain accessible if intentionally available;
- loaded content regains semantics;
- failure replaces loading semantics.
Do not use
Skeleton.ignoreas a semantics mechanism.
Step 11 — Motion and theme
Use application-level Skeletonizer configuration for consistent effects. Prefer:
ShimmerEffectfor ordinary measured animation;PulseEffectwhen lower-spatial-motion treatment suits UX;SolidColorEffectfor reduced motion, deterministic tests, or performance-sensitive cases. Honor:
MediaQuery.disableAnimationsOf(context)Do not hardcode one light shimmer palette into dark mode. Enable skeleton→content switch animation only when the UX benefit justifies extra transition/state/paint complexity. Do not assume switch animation for slivers.
Step 12 — State-management boundary
State management exposes semantic phases and real data. Presentation chooses Skeletonizer. Good:
Cubit/Notifier:
initialLoading / loaded / refreshing / loadingMore / failure
real data only
Widget:
maps phase to skeleton / content / refresh / pagination / errorKeep these package types out of repositories/domain code:
Skeletonizer
Bone
ShimmerEffect
Permission-like UI config
placeholder domain entitiesUse selectors/build filters so unrelated state changes do not rebuild giant animated skeleton subtrees.
Step 13 — Errors and retries
Required state transition:
loading
├── success → real content
└── failure → error/retry UINever infer loading from data == null if null also represents failure.
With useful cached content and refresh failure, keep content and surface a non-destructive error.
Step 14 — Test deterministically
Use SolidColorEffect when animation is irrelevant to the test.
Test:
- skeleton on/off;
- initial → loaded;
- initial → failure;
- refresh keeps content;
- pagination keeps rows and appends placeholders;
- pointer blocking;
- local interaction guards;
replacebehavior;- semantics exclusion/loading status;
- reduced motion;
- responsive layout;
- important light/dark skeleton goldens. For migration-sensitive visual changes, capture baseline goldens before upgrading the package.
Step 15 — Profile measured hotspots
Use profile mode and representative physical hardware. Compare skeleton vs loaded state:
UI-thread time
raster-thread time
jank count
rebuilds
memory
image/decode activity
platform-view activityIf skeleton state is more janky than loaded content, optimize in this order:
- reduce placeholder count;
- preserve lazy construction;
- replace complex descendants;
- stop unnecessary image/network work;
- remove costly
shade/nested skeleton scopes; - simplify or disable animation;
- narrow skeleton scope;
- only then test targeted repaint boundaries. Keep only improvements supported by measurement.
Migration rules
Before upgrading Skeletonizer:
- inspect current and target SDK constraints;
- read intervening changelog entries;
- search all Skeletonizer APIs;
- preserve loading semantics and geometry;
- inspect deprecated/renamed APIs;
- test annotations and custom effects;
- run widget/accessibility/golden tests;
- profile large loading surfaces again. Known source-baseline concerns include:
Skeletonizer.bones → Skeletonizer.zone
SkeletonizerConfigData.light() → default constructor
SoldColorEffect → SolidColorEffect
old colored-box annotation removed
switch animation introduced later
ThemeExtension support introduced later
TextBoneBorderShape additions
sliver switch-animation limitationsDo not copy current-baseline APIs into an older locked project without verification.
Review output format
When reviewing existing code, report findings in this order:
- Loading-state correctness — initial vs refresh vs pagination vs mutation.
- Architecture — fake-data leakage, ownership, state-management boundaries.
- Layout stability — dimensions, text lines, responsive parity.
- Interaction safety — fake actions, scrolling/hit testing.
- Accessibility — placeholder semantics, loading status, reduced motion.
- Expensive descendants — images/charts/platform views still initializing.
- Performance — placeholder count, lazy construction, effect/paint scope.
- Version/API risks — deprecated or unsupported Skeletonizer APIs.
- Tests — transition, semantics, responsive, golden, profiling gaps.
- Prioritized fixes — correctness/security/accessibility first, polish last.
Production gate
Approve only when all are true:
- loading scenario is correctly classified;
- skeleton is the right UX for that scenario;
- fake values are presentation-only;
- initial/refresh/pagination/mutation states differ appropriately;
- final geometry is closely preserved;
- lists/grids are lazy and bounded;
- heavy descendants are replaced/deferred when appropriate;
- placeholder controls cannot act;
- fake semantics are excluded;
- loading is communicated accessibly;
- reduced motion is handled;
- light/dark/responsive/localized layouts are tested;
- failure stops skeleton loading;
- current package APIs are verified;
- important transitions have deterministic tests;
- complex animated skeletons have profile-mode evidence.
Final operating rule
Before adding or changing Skeletonizer code, answer:
What user operation is happening?
Should it use a skeleton at all?
Is useful content already available?
Is final structure predictable?
Can the real layout be built safely?
Where will placeholder geometry live?
Can fake data escape presentation?
Which descendants must be replaced/deferred?
Can any fake control be interacted with?
Can fake content enter semantics?
Does motion/theme/accessibility policy fit?
Is placeholder count bounded and lazy?
Does failure terminate loading?
Has expensive/repeated rendering been profiled?Use Skeletonizer as a presentation painting tool, not as a substitute for state modeling, caching, progress reporting, accessibility, or performance engineering.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

