animate-my-app 1.0.0 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -50,22 +50,19 @@ The skill scaffolds an app with `scripts/new_app.sh`, builds it, runs it in the
50
50
  - Claude Code
51
51
  - Optional: an Apple developer team ID to run on your own iPhone; the Figma MCP server for Figma links
52
52
 
53
- **Optional companion skills.** If these are installed, the skill loads them; otherwise it uses its own rules:
54
- `motion-design`, `apple-design`, `emil-design-eng`, `micro-interactions`, and Figma's official skills.
55
-
56
53
  ## What's inside
57
54
 
58
55
  ```
59
56
  skills/animate-my-app/
60
57
  ├── SKILL.md the workflow and the rules
61
- ├── references/ stack, motion physics, procedural 3D, testing, research and tools, lessons learned
58
+ ├── references/ craft guide, stack, motion physics, procedural 3D, testing, research and tools, lessons learned
62
59
  ├── scripts/ new_app.sh scaffold, frame extraction, hitch probe, framed video, SF Symbol export
63
60
  └── assets/template/ a working SwiftUI + three.js app the scaffold copies
64
61
  ```
65
62
 
66
- ## Credits
63
+ ## Author
67
64
 
68
- Built by [@oiharshit](https://x.com/oiharshit). It builds on three.js (MIT), Emil Kowalski's design-engineering teaching and Apple's WWDC talk *Designing Fluid Interfaces*; see [CREDITS.md](CREDITS.md).
65
+ Made by [@oiharshit](https://x.com/oiharshit).
69
66
 
70
67
  ## License
71
68
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "animate-my-app",
3
- "version": "1.0.0",
3
+ "version": "1.1.0",
4
4
  "description": "A Claude Code skill: turn an app design into a native, animated iOS app (SwiftUI + three.js), tested on device. Run `npx animate-my-app` to install.",
5
5
  "bin": {
6
6
  "animate-my-app": "bin/install.js"
@@ -9,8 +9,7 @@
9
9
  "bin/",
10
10
  "skills/",
11
11
  "README.md",
12
- "LICENSE",
13
- "CREDITS.md"
12
+ "LICENSE"
14
13
  ],
15
14
  "keywords": [
16
15
  "claude",
@@ -13,7 +13,7 @@ description: >
13
13
  license: MIT
14
14
  metadata:
15
15
  author: "@oiharshit"
16
- version: "1.0.0"
16
+ version: "1.1.0"
17
17
  ---
18
18
 
19
19
  # Animate My App
@@ -22,14 +22,11 @@ Take a designed app screen (usually from Figma) and ship it as a native iOS app
22
22
  Rive- or three.js-level piece: physical, staged, measured. Speed comes from **reusing this pipeline** (scaffold,
23
23
  engine, test scripts, recipes), not re-deriving it for every app.
24
24
 
25
- ## 0. Before anything: optional companion skills
25
+ ## 0. Before anything: read the craft guide
26
26
 
27
- If these skills are installed, load them (Skill tool) at the start of a build; they raise the motion and design bar:
28
- `motion-design`, `apple-design`, `emil-design-eng`, `micro-interactions`.
29
- Add as relevant when installed: `figma-design-to-code` (required before the Figma MCP `get_design_context` tool),
30
- `figma-implement-motion` (Figma motion data), `figma-swiftui`, `interaction-design`, `lottie-motion-design`
31
- (Lottie), typography/UI polish skills.
32
- If none are installed, follow the rules in this skill and its references; they are self-contained.
27
+ Read `references/craft.md` at the start of every build. It sets the bar for motion, interaction, accessibility,
28
+ visual polish, typography, colour and Figma-to-code fidelity, and ends with the review checklist to run before
29
+ you report. This skill is self-contained: everything it needs is in this folder.
33
30
 
34
31
  ## 1. Intake (fast), then ASK
35
32
 
@@ -68,8 +65,9 @@ swappable pieces: `references/photo-layers.md`.
68
65
 
69
66
  ## 3. Motion rules
70
67
 
71
- Full formulas and constants: `references/motion-physics.md`.
72
- - Real physics: damped springs (Apple damping/response), gravity drops, squash and stretch that **preserves
68
+ Full formulas and constants: `references/motion-physics.md`; timing, easing, gestures and polish:
69
+ `references/craft.md`.
70
+ - Real physics: damped springs (damping ratio + response), gravity drops, squash and stretch that **preserves
73
71
  volume**, contact shadows that react to height.
74
72
  - Anticipation without dwell: squeeze, then stretch **and** move on the same frame; peak stretch early in the
75
73
  travel; jelly follow-through; overshoot then a braking squash. Stretch must be clearly visible.
@@ -0,0 +1,191 @@
1
+ # Craft: motion, interaction and visual polish
2
+
3
+ The bar every screen is held to. Read it at the start of a build and again before you report. Physics formulas and
4
+ measured constants live in `motion-physics.md`; this file is the judgement around them.
5
+
6
+ ## 1. Decide before you animate
7
+
8
+ Ask three questions for every moving thing:
9
+
10
+ 1. **How often will someone see it?**
11
+ - Many times a minute (typing, keyboard shortcuts, scrolling a list): no animation, or an instant state change.
12
+ - Many times a day (tabs, toggles, row taps): short and quiet, 100–200 ms, no bounce.
13
+ - Now and then (sheets, menus, toasts, page changes): a normal transition, 200–350 ms.
14
+ - Once (splash, onboarding, a first success, a celebration): this is where the hero motion goes. Longer and
15
+ richer is fine, but it must still be skippable and must not block input.
16
+ 2. **What job does it do?** Give it one: show where something came from or went (spatial continuity), confirm an
17
+ action (feedback), show a state change, explain how something works, or soften a change that would otherwise
18
+ jump. "It looks nice" alone is only enough for rare moments.
19
+ 3. **Does it still work with no motion at all?** It must. Motion explains and rewards; the screen must never depend
20
+ on it to be understood.
21
+
22
+ Restraint is part of the craft: one hero moment per screen, everything else supports it.
23
+
24
+ ## 2. Timing and easing
25
+
26
+ | What | Duration | Curve |
27
+ |---|---|---|
28
+ | Press feedback (scale, dim) | 80–150 ms | ease-out |
29
+ | Small state change (toggle, check, colour) | 120–200 ms | ease-out |
30
+ | Tooltip, small popover, menu | 150–220 ms | ease-out, from its trigger |
31
+ | Sheet, modal, drawer | 250–400 ms | spring, no or little bounce |
32
+ | Page or screen change | 300–450 ms | spring or strong ease-in-out |
33
+ | Hero / onboarding moment | as long as the story needs | physics (motion-physics.md) |
34
+
35
+ - **Exits are faster than entrances**, about 60–75 % of the entrance time. Leaving should never hold up the user.
36
+ - **Entering → ease-out** (starts fast, so the response feels instant). **Moving on screen → ease-in-out.**
37
+ **Constant motion (spinners, marquees, progress) → linear.** Avoid plain ease-in for UI: the slow start reads as lag.
38
+ - The stock curves are too soft. Use strong ones:
39
+ - ease-out: `cubic-bezier(0.22, 1, 0.36, 1)`
40
+ - ease-in-out: `cubic-bezier(0.76, 0, 0.24, 1)`
41
+ - sheet / drawer: `cubic-bezier(0.3, 0.75, 0.05, 1)`
42
+ - Faster feels better. A loader that spins quicker makes the same wait feel shorter; a 180 ms menu feels more
43
+ responsive than a 350 ms one.
44
+ - Stagger lists and grouped entrances 30–60 ms per item, capped so the last item starts within ~300 ms.
45
+
46
+ ## 3. Springs
47
+
48
+ Springs are the default for anything that moves on screen, because they can be interrupted and they keep velocity.
49
+
50
+ - Describe springs the way iOS does: **damping ratio** (1 = no overshoot, 0.7–0.85 = a little life, < 0.6 = playful)
51
+ and **response** (seconds to get most of the way there).
52
+ - Standard UI move: damping 1.0, response 0.35–0.45.
53
+ - Something thrown or flicked: damping 0.75–0.85, response 0.5–0.6.
54
+ - Playful pop (badge, sticker, success mark): damping 0.5–0.65, response 0.3–0.4.
55
+ - SwiftUI: `.spring(duration: 0.4, bounce: 0)` for UI, `bounce: 0.15–0.3` only where play is wanted;
56
+ `.snappy` for small controls, `.smooth` for layout, `.interactiveSpring` while a finger is down.
57
+ - Keep bounce out of serious, frequent UI (settings, forms, money). Put it where touch or delight lives.
58
+ - **Interruptible always:** a new target starts from the current value and velocity, never from the start.
59
+ Keyframe or fixed-duration animations restart from zero, so don't use them for anything a user can interrupt.
60
+
61
+ ## 4. Entrances, exits and presses
62
+
63
+ - Nothing appears from nothing: enter from scale 0.9–0.97 plus opacity, or slide a short distance (8–24 pt) plus
64
+ opacity. Never from `scale(0)`.
65
+ - Things leave the way they came, so the user's mental map holds (a toast that rose from the bottom drops back down).
66
+ - Popovers and menus grow from the control that opened them; full-screen modals grow from the centre.
67
+ - Every pressable thing answers the touch: scale 0.96–0.98 or a dim, on touch-down, released with a quick spring,
68
+ plus a light haptic for primary actions.
69
+ - When a cross-fade between two states looks like two objects swapping, add a short blur (2–4 px) at the midpoint
70
+ so the eye reads one thing changing.
71
+ - Solid objects that overlap should not fade in (they turn see-through); fade only soft things like glows.
72
+
73
+ ## 5. Gestures
74
+
75
+ - The thing under the finger moves 1:1 with it. No lag, no easing while dragging.
76
+ - On release, hand the finger's velocity to the spring (`initialVelocity = finger speed / remaining distance`).
77
+ - **Decide by projection, not position:** project where a flick would land
78
+ (`end = position + velocity × decelerationRate / (1 − decelerationRate)` with rate ≈ 0.998 per ms) and snap to the
79
+ nearest stop. A quick flick should be enough to dismiss; nobody should have to drag past a far line.
80
+ - Past a limit, resist instead of stopping dead: `offset = limit × (1 − 1 / (overshoot / limit × 0.55 + 1))`.
81
+ - Once a drag starts, ignore extra fingers, and keep tracking even if the finger leaves the element.
82
+ - Let a moving thing be grabbed mid-flight; never lock input during an animation unless the action is destructive.
83
+ - Give a haptic tick when a threshold is crossed (snap points, pull-to-refresh trigger), once per crossing.
84
+
85
+ ## 6. Interaction anatomy
86
+
87
+ Write every interaction down as four parts before building it:
88
+
89
+ 1. **Trigger**: what starts it (tap, long press, drag, a value change, the system).
90
+ 2. **Rules**: what is allowed while it runs, what cancels it, the end states.
91
+ 3. **Feedback**: what the user sees, feels (haptic) and hears (only if sound was asked for).
92
+ 4. **Repeat and change**: what happens the second and the hundredth time; whether it should calm down.
93
+
94
+ Patterns that hold up on iOS:
95
+
96
+ - **Button:** press scale 0.97 + dim, loading swaps the label for a spinner at the same size (no width jump),
97
+ success morphs to a check for ~1 s, then returns.
98
+ - **Toggle:** knob on a stiff spring, track colour fades with it, a selection haptic at the end.
99
+ - **Sheet:** follows the finger, snaps to detents by projection, dim behind it at ~20 %, no full-screen blur.
100
+ - **Toast:** rises 12–16 pt with opacity, auto-dismisses after 3–4 s, can be swiped away, announced to VoiceOver.
101
+ - **Error:** a short horizontal shake (3 cycles, ~6 pt, 300 ms) plus an error haptic and a clear message; never
102
+ shake without saying what is wrong.
103
+ - **Loading:** a skeleton that matches the real layout for waits over ~300 ms, a spinner only for small areas;
104
+ content cross-fades in, never pops.
105
+ - **Counters and numbers:** roll digits with tabular figures so the width doesn't jitter.
106
+ - **Pull-to-refresh / swipe actions:** reveal grows with the pull, a haptic at the trigger point, spring back if
107
+ released early.
108
+
109
+ Haptics map: light impact for presses, selection for picking and snapping, success / warning / error notifications
110
+ for outcomes, medium or heavy only for something physical landing. Prepare the generator before the moment.
111
+
112
+ ## 7. Accessibility
113
+
114
+ - Always build the reduced-motion version: same order, short cross-fades, no squash, overshoot, spin or parallax.
115
+ SwiftUI `@Environment(\.accessibilityReduceMotion)`; in the web layer read the flag from native.
116
+ - Touch targets at least 44 × 44 pt even when the visible control is smaller (expand the hit area, not the drawing).
117
+ - Text contrast at least 4.5:1 (3:1 for large text and icons). Check muted greys and brand colours on their
118
+ real backgrounds, in light and dark.
119
+ - Support Dynamic Type for reading text; let layouts wrap instead of truncating.
120
+ - Every icon-only button gets an accessibility label; announce toasts and results.
121
+ - Never convey state by colour alone; pair it with an icon, a label or a shape.
122
+
123
+ ## 8. Performance
124
+
125
+ - Animate transforms and opacity. Animating size, padding or layout re-lays out every frame.
126
+ - In SwiftUI, keep animated views small and isolated; avoid animating a view whose body does heavy work, and avoid
127
+ large `.blur` or material changes per frame.
128
+ - In the web layer: one render loop, no per-frame allocations, textures uploaded before the clock starts.
129
+ - Budget: 60 fps (16.7 ms) on device, 0 frames over 25 ms on a replay. Measure, don't eyeball (testing.md).
130
+ - Low Power Mode caps web views at 30 fps; turn it off before judging performance on a phone.
131
+
132
+ ## 9. Visual polish
133
+
134
+ - **Concentric corners:** outer radius = inner radius + padding (see SKILL.md).
135
+ - **Optical alignment:** centre icons and play triangles by eye, not by box (a triangle sits ~1–2 pt right of centre);
136
+ round shapes slightly overshoot the line that square shapes sit on.
137
+ - **Depth:** build shadows from two or three layers (a tight dark contact shadow plus a wide soft ambient one),
138
+ tinted by the surface colour, never a single grey blur. Lifted things get softer, wider shadows.
139
+ - **Borders:** hairlines at 0.5–1 pt with low-alpha ink read cleaner than solid grey lines; on dark surfaces, a light
140
+ top edge sells depth.
141
+ - **Spacing:** pick one 4 pt grid and keep it; equal gaps where things are related, bigger gaps between groups.
142
+ Measure from the visible edge.
143
+ - **Icons:** one family, one weight, sized to the text they sit beside; icons that change with state should morph or
144
+ cross-fade, not snap.
145
+ - **States:** design every control for rest, pressed, disabled, loading, error and empty, before calling it done.
146
+
147
+ ## 10. Typography
148
+
149
+ - SF Pro (or the design's font) with the platform's size-specific tracking: large titles slightly loose, body near
150
+ 0, small captions a little open. Copy the Figma letter spacing exactly when given.
151
+ - Line height about 1.2–1.3 for headings, 1.4–1.5 for reading text; tighter for big display type.
152
+ - Use tabular figures for anything that counts, ticks or aligns in columns (`.monospacedDigit()`).
153
+ - Hierarchy from size and weight first, colour second. Two or three sizes per screen is usually enough.
154
+ - Balance short headlines so they don't leave a single word on the last line; never truncate a headline.
155
+ - Use real quotes and apostrophes (’ “ ”), a real ellipsis (…) and non-breaking spaces between numbers and units.
156
+
157
+ ## 11. Colour
158
+
159
+ - Define colours as named roles (background, surface, ink, muted ink, accent, danger), with light and dark values,
160
+ and use the roles, never raw hex in views.
161
+ - Dark mode is not inverted light mode: lift surfaces with lightness, mute bright accents, avoid pure white text on
162
+ pure black for long reading.
163
+ - Tint neutrals slightly toward the brand hue so greys don't look dead.
164
+
165
+ ## 12. From Figma to code
166
+
167
+ 1. Pull ground truth first: a screenshot of the frame, then the design context (sizes, colours, fonts, effects),
168
+ then the node tree. Treat generated code from Figma as a reference to translate into SwiftUI, never as final code.
169
+ 2. Reuse what the project already has (components, spacing, colour roles) before creating anything new.
170
+ 3. Export every icon and image from the file at full scale; never redraw an icon by hand or leave a placeholder.
171
+ SF Symbols map back to `Image(systemName:)` by name.
172
+ 4. Derive the arithmetic (grid, spacing steps, radii, type scale) instead of copying one-off numbers.
173
+ 5. If the file has prototype motion, read its timing and curves and match them; Smart Animate durations are the
174
+ designer's intent.
175
+ 6. Prove fidelity by measuring: put the build next to the Figma screenshot at the same scale and compare positions,
176
+ sizes and colours numerically (research-and-tools.md, testing.md). Fix until they match.
177
+
178
+ ## 13. Rive and Lottie
179
+
180
+ Use them when the design ships `.riv` or Lottie files, or when the part is classic 2D vector character animation.
181
+ Play supplied files as they are; don't rebuild them by hand. Keep text and buttons native on top, and preload the
182
+ file before the first frame like any other asset.
183
+
184
+ ## 14. Review before you report
185
+
186
+ - Does each animation have one job, and is frequent motion short and quiet?
187
+ - Entrances ease-out, exits faster, nothing from scale 0, presses answer on touch-down?
188
+ - Springs interruptible, velocity carried from gestures, flicks decided by projection?
189
+ - Reduced-motion path built and checked? Hit areas 44 pt? Contrast measured?
190
+ - Nothing clipped, concentric corners, consistent spacing and icon weights?
191
+ - Numbers measured on device: frame times, arrival before the next phase, alignment with the design?
@@ -208,7 +208,7 @@ headline out of step. Rendering was fine; the gesture state machine wasn't robus
208
208
  - Paired elements (dim + card, fog + composer) must use the same animation; check both modifiers.
209
209
  - Don't animate a full-screen `.blur` behind a sheet: expensive per frame on device and reads as lag; dim alone (~22 %).
210
210
  - Switching `.preferredColorScheme` at a light→dark transition flips the status bar instantly; flip it at mid-fade.
211
- - **Motion tokens in SwiftUI** (Emil Kowalski's animation guidance, translated): `.spring(duration:bounce: 0)`
211
+ - **Motion tokens in SwiftUI** (see craft.md): `.spring(duration:bounce: 0)`
212
212
  tokens; asymmetric transitions with a faster `.easeIn` removal via `.transition(.x.animation(...))`; a `Motion.x(reduceMotion) -> Animation?` helper returning nil.
213
213
  List rows: inset highlight (rounded rect, on instantly, 0.25 s fade out), not a scale.
214
214
  - **Drag to dismiss:** carry velocity with `.interpolatingSpring(duration:bounce:initialVelocity:)` where
@@ -1,10 +1,10 @@
1
1
  # Inputs, references and generators — with fallbacks
2
2
 
3
3
  ## Figma (the usual input)
4
- - If installed, load `figma-design-to-code` before `get_design_context` (the Figma MCP expects it).
4
+ - Follow the Figma-to-code steps in `craft.md` (section 12).
5
5
  - Per linked node: `get_screenshot` (ground truth), `get_design_context` (sizes, colours, fonts, effects),
6
6
  `get_metadata` (tree), `download_assets` for raster art/illustrations at the highest scale, fonts used.
7
- Motion data in the file → `get_motion_context` (+ `figma-implement-motion` if installed).
7
+ Motion data in the file → `get_motion_context`.
8
8
  - If the Figma MCP needs auth, ask for it to be authorised via `/mcp`. Meanwhile, if the frame is open in Figma
9
9
  (desktop or browser), export via a browser/computer-use route. Ask rather than guessing from a low-res
10
10
  screenshot when exact assets matter.
@@ -87,8 +87,7 @@
87
87
  - 9:16 concept frames work well for "pick one of 4" motion directions before building.
88
88
 
89
89
  ## Rive / Lottie
90
- - Supplied `.riv` or Lottie JSON → use them (Rive runtime in the web layer or rive-ios; Lottie, with
91
- `lottie-motion-design` if installed). Don't recreate a supplied vector animation by hand.
90
+ - Supplied `.riv` or Lottie JSON → use them (Rive runtime in the web layer or rive-ios; lottie-ios for Lottie). Don't recreate a supplied vector animation by hand.
92
91
 
93
92
  ## When to ask (always allowed)
94
93
  - Motion intent, sequence, feel, length, sound — before building (2–4 questions).
@@ -65,4 +65,4 @@ is identical on every replay.
65
65
  - SwiftUI: all UI chrome, text, buttons, list/screen transitions (`matchedGeometryEffect`, `PhaseAnimator`,
66
66
  `KeyframeAnimator`, springs). Keep text native (crisp, accessible, exact font).
67
67
  - Rive / Lottie: only when `.riv` / Lottie JSON is supplied or the part is classic 2D vector character
68
- animation (load `lottie-motion-design` if installed). Rive runtime can also run in the web layer.
68
+ animation. Rive runtime can also run in the web layer.
package/CREDITS.md DELETED
@@ -1,17 +0,0 @@
1
- # Credits
2
-
3
- animate-my-app is written by [@oiharshit](https://x.com/oiharshit). It stands on other people's work:
4
-
5
- - **three.js** (r159), bundled in the app template at `skills/animate-my-app/assets/template/__APP__/Web/three.min.js`.
6
- Copyright 2010-2023 three.js authors, MIT licence (the notice is kept in the file). https://threejs.org
7
- - **Emil Kowalski**: the motion and polish rules this skill follows (strong ease-out curves, no entrances from
8
- `scale(0)`, 0.97 press feedback, restraint) come from his design-engineering teaching. His course:
9
- https://animations.dev. If you have his `emil-design-eng` / `emil-animations` skills installed, this skill loads them.
10
- - **Apple, WWDC "Designing Fluid Interfaces" (2018)**: springs described by damping ratio and response,
11
- interruptible motion and velocity hand-off.
12
- - **Companion skills** that animate-my-app loads when you have them installed (optional, not included here, credit to
13
- their authors): `motion-design`, `apple-design`, `micro-interactions`, `interaction-design`, `lottie-motion-design`,
14
- `better-ui`, `better-typography`, and Figma's official skills (`figma-design-to-code`, `figma-implement-motion`,
15
- `figma-swiftui`).
16
- - **Apple SF Symbols**: `scripts/sf_symbol_bitmap.swift` renders symbols from your own Mac for use in your apps;
17
- follow Apple's SF Symbols licence terms.