compose-modifier-system

Enforce correct modifier state read phases and invalidation in Jetpack Compose.

1|1|Updated May 23, 2026
One-click install
npx skills add https://github.com/santimattius/performance-compose-skills --skill compose-modifier-system
Or copy as Structured Prompt for Agent
Please help me install this Agent Skill.
Skill: compose-modifier-system
Source: https://github.com/santimattius/performance-compose-skills/tree/main/skills/compose-modifier-system
Command: npx skills add https://github.com/santimattius/performance-compose-skills --skill compose-modifier-system

SYSTEM DOCUMENTATION & REQUIREMENTS

💡 This Skill includes references (resource) components.

What problem does it solve?

This Skill helps you stop Compose modifier code from triggering expensive recompositions by reading state in the wrong phase, and it shows how to build custom modifiers that invalidate only what’s necessary.

Core Features & Use Cases

  • Defer state reads to Layout/Drawing: Use lambda overloads like Modifier.offset { ... } and Modifier.graphicsLayer { ... } so frequently changing values don’t force Composition restarts.
  • Use production-ready custom modifiers: Replace deprecated Modifier.composed with ModifierNodeElement + Modifier.Node, using correct equality semantics and fine-grained invalidation.
  • Pick the right drawing tier: Choose drawBehind, drawWithContent, or drawWithCache based on whether drawing is simple, ordering-sensitive, or requires cached expensive objects.
  • Avoid common layout/draw pitfalls: Prevent measuring children twice in custom layout and ensure pixel-vs-dp correctness in drawing.

Quick Start

Use this skill to revise a custom modifier so that scroll/animation state is read in the Layout or Drawing phase, and to ensure the modifier node invalidates only placement or drawing when its inputs change.

Frequently Asked Questions about compose-modifier-system

High-intent search queries and answers about installing and using this skill.

FAQPage Schema
How do I prevent unnecessary Jetpack Compose recomposition from modifier state reads?

Prevent unnecessary Jetpack Compose recomposition by deferring state reads to the Layout or Drawing phase using lambda overloads like Modifier.offset { ... } and Modifier.graphicsLayer { ... }, ensuring frequently changing values do not force Composition restarts.

When should I use drawWithCache versus drawBehind in Compose custom modifiers?

Choose drawWithCache when your drawing requires cached expensive objects, drawBehind for simple drawing, and drawWithContent when ordering-sensitive drawing is needed, ensuring correct drawing tier selection for optimal Compose modifier performance.

How do I migrate from deprecated Modifier.composed to ModifierNodeElement?

Migrate from deprecated Modifier.composed by implementing ModifierNodeElement with Modifier.Node, using correct equality semantics and fine-grained invalidation like invalidatePlacement or invalidateDraw to control which phase updates.

Why does my custom Compose layout measure children twice?

Your custom Compose layout measures children twice due to incorrect layout modifier implementation. Prevent this by properly structuring custom layout logic and ensuring pixel-vs-dp correctness in drawing to avoid redundant measurement passes.

Can I control invalidation scope in Compose Modifier.Node?

Yes, you can control invalidation scope in Compose Modifier.Node by using invalidatePlacement for layout changes and invalidateDraw for drawing updates, ensuring only the necessary frame phase restarts instead of triggering full recomposition.

What is the best way to handle scroll and animation state in Compose modifiers?

The best way to handle scroll and animation state in Compose modifiers is to read the state within the Layout or Drawing phase using lambda overloads, and ensure the modifier node invalidates only placement or drawing when its inputs change.