@minhduydev/mdpi 0.4.1 → 0.5.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.
Files changed (34) hide show
  1. package/dist/index.js +1 -1
  2. package/dist/template/.pi/VERSION +1 -1
  3. package/dist/template/.pi/extensions/templates-injector.ts +35 -7
  4. package/dist/template/.pi/prompts/INDEX.md +3 -9
  5. package/dist/template/.pi/skills/INDEX.md +39 -8
  6. package/dist/template/.pi/skills/dcp-hygiene/SKILL.md +1 -1
  7. package/dist/template/.pi/skills/frontend-design/SKILL.md +1 -1
  8. package/dist/template/.pi/skills/frontend-design/references/animation/motion-advanced.md +88 -15
  9. package/dist/template/.pi/skills/frontend-design/references/animation/motion-core.md +148 -13
  10. package/dist/template/.pi/skills/frontend-design/references/shadcn/setup.md +127 -20
  11. package/dist/template/.pi/skills/nextjs-app-router/SKILL.md +334 -0
  12. package/dist/template/.pi/skills/nextjs-cache/SKILL.md +262 -0
  13. package/dist/template/.pi/skills/react-best-practices/SKILL.md +79 -1
  14. package/dist/template/.pi/skills/react-compiler/SKILL.md +237 -0
  15. package/dist/template/.pi/skills/react-hook-form/SKILL.md +374 -0
  16. package/dist/template/.pi/skills/react-server-actions/SKILL.md +299 -0
  17. package/dist/template/.pi/skills/shadcn-ui/SKILL.md +404 -0
  18. package/dist/template/.pi/skills/tanstack-query/SKILL.md +330 -0
  19. package/dist/template/.pi/skills/v0/SKILL.md +264 -0
  20. package/dist/template/.pi/skills/zustand/SKILL.md +333 -0
  21. package/package.json +1 -1
  22. package/dist/template/.pi/prompts/loop-check.md +0 -87
  23. package/dist/template/.pi/prompts/loop-init.md +0 -157
  24. package/dist/template/.pi/prompts/loop-review.md +0 -90
  25. package/dist/template/.pi/skills/loop-audit/SKILL.md +0 -141
  26. package/dist/template/.pi/skills/loop-cost/SKILL.md +0 -130
  27. package/dist/template/.pi/skills/loop-engineering/SKILL.md +0 -175
  28. package/dist/template/.pi/templates/loop-github-action.yml +0 -162
  29. package/dist/template/.pi/templates/loop-orchestrator.sh +0 -514
  30. package/dist/template/.pi/templates/loop-orchestrator.test.ts +0 -332
  31. package/dist/template/.pi/templates/loop-orchestrator.ts +0 -936
  32. package/dist/template/.pi/templates/loop-state.json +0 -24
  33. package/dist/template/.pi/templates/loop-state.md +0 -98
  34. package/dist/template/.pi/templates/loop-vision.md +0 -110
package/dist/index.js CHANGED
@@ -10,7 +10,7 @@ import { spawn, spawnSync } from "node:child_process";
10
10
  import { fileURLToPath } from "node:url";
11
11
  import { mkdir, readdir } from "node:fs/promises";
12
12
  //#region package.json
13
- var version = "0.4.1";
13
+ var version = "0.5.0";
14
14
  //#endregion
15
15
  //#region src/utils/manifest.ts
16
16
  /**
@@ -1 +1 @@
1
- 0.4.1
1
+ 0.5.0
@@ -1,7 +1,6 @@
1
1
  /**
2
2
  * Templates Injector Extension
3
3
  *
4
- * Auto-injects project context files into system prompt.
5
4
  * Auto-injects project context files into system prompt via pi's before_agent_start hook.
6
5
  *
7
6
  * Resolution: prefer the LIVE file at `.pi/{name}` (filled by /init, the project's
@@ -9,21 +8,40 @@
9
8
  * when no live file exists. This keeps templates/ pristine as deliverables while
10
9
  * ensuring real project state is what the agent actually sees.
11
10
  *
12
- * Auto-injected (always, whichever resolves):
11
+ * Auto-injected (always, whichever resolves) — but ONLY when not placeholder-heavy:
13
12
  * - project.md
14
13
  * - tech-stack.md
15
14
  * - state.md ← the "you are here" marker; live version injected once /init fills it
16
15
  *
17
- * User can opt-in to inject more via /inject-template command.
16
+ * Placeholder-skip: at before_agent_start, blank seed templates (still full of
17
+ * `[Criterion]`/`[URL]`/`<!-- ... -->` markers) are skipped so they don't tax the
18
+ * first message. A live file with real content (few markers) still injects.
19
+ *
20
+ * DESIGN.md is NOT auto-injected — load it on demand via `/inject-template DESIGN.md`
21
+ * (e.g. when starting UI work).
22
+ *
23
+ * User can opt-in to inject more via /inject-template command (placeholder-skip
24
+ * does not apply to explicit on-demand injection).
18
25
  */
19
26
 
20
27
  import * as fs from "node:fs";
21
28
  import * as path from "node:path";
22
29
  import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
23
30
 
24
- const ALWAYS_INJECT = ["project.md", "tech-stack.md", "state.md", "DESIGN.md"];
31
+ const ALWAYS_INJECT = ["project.md", "tech-stack.md", "state.md"];
25
32
 
26
- function readTemplate(cwd: string, name: string): string | null {
33
+ // Placeholder markers that indicate a template is still a blank seed (not filled).
34
+ // Counted to decide whether an auto-injected file would just add noise to the
35
+ // first message. Threshold is intentionally low (>5) so a genuinely filled live
36
+ // file (a handful of incidental bracket occurrences) still injects.
37
+ const PLACEHOLDER_MARKER_RE = /\[(?:e\.g\.|Criterion|URL|Title|Date|slug)[^\]]*\]|<slug>|<!-- /g;
38
+ const PLACEHOLDER_MARKER_THRESHOLD = 5;
39
+
40
+ function readTemplate(
41
+ cwd: string,
42
+ name: string,
43
+ skipPlaceholders = false,
44
+ ): string | null {
27
45
  // Prefer live file at .pi/{name} (filled by /init — real project state);
28
46
  // fall back to blank seed at .pi/templates/{name} when no live file exists.
29
47
  const livePath = path.join(cwd, ".pi", name);
@@ -33,7 +51,17 @@ function readTemplate(cwd: string, name: string): string | null {
33
51
  const content = fs.readFileSync(filePath, "utf-8");
34
52
  // Strip frontmatter for injection
35
53
  const fmMatch = content.match(/^---\n[\s\S]*?\n---\n([\s\S]*)$/);
36
- return (fmMatch ? fmMatch[1] : content).trim();
54
+ const body = (fmMatch ? fmMatch[1] : content).trim();
55
+ // Auto-inject only: skip placeholder-heavy files so unfilled templates don't
56
+ // tax the first message. On-demand /inject-template bypasses this (default).
57
+ // Anchored to a closing `]` so real markdown links like `[Vercel](...)` don't
58
+ // count; only placeholder-shaped tokens (`[URL]`, `[Criterion 1]`, `[e.g., ...]`,
59
+ // `<slug>`, `<!-- `) do.
60
+ if (skipPlaceholders) {
61
+ const markers = body.match(PLACEHOLDER_MARKER_RE);
62
+ if (markers && markers.length > PLACEHOLDER_MARKER_THRESHOLD) return null;
63
+ }
64
+ return body;
37
65
  }
38
66
 
39
67
  export default function templatesInjector(pi: ExtensionAPI) {
@@ -41,7 +69,7 @@ export default function templatesInjector(pi: ExtensionAPI) {
41
69
  const injected: string[] = [];
42
70
 
43
71
  for (const name of ALWAYS_INJECT) {
44
- const content = readTemplate(ctx.cwd, name);
72
+ const content = readTemplate(ctx.cwd, name, /* skipPlaceholders */ true);
45
73
  if (content && content.length > 0) {
46
74
  injected.push(`### ${name}\n\n${content}`);
47
75
  }
@@ -4,7 +4,7 @@ purpose: Index of slash commands with purpose, when-to-use, and lifecycle positi
4
4
 
5
5
  # Prompts Index
6
6
 
7
- 14 slash commands. Lifecycle is canonical; utilities attach at any phase.
7
+ 11 slash commands. Lifecycle is canonical; utilities attach at any phase.
8
8
 
9
9
  ## Canonical Lifecycle
10
10
 
@@ -39,9 +39,6 @@ Status: /status
39
39
  | `/gc` | Fallow analysis + quality grades + optional cleanup PRs | Maintenance cadence; not during active feature work | `[--dry-run] [--apply] [--scope <dir>]` | Maintenance |
40
40
  | `/status` | Show active feature, progress tail, blockers | Orient at session start or when unsure | `[--full]` | Any (read-only) |
41
41
  | `/close` | Finalize active feature, clear `.active` | Feature done/blocked/abandoned, or recover dangling `.active` | `[--done\|--blocked\|--abandoned] [--note <text>]` | Ship/Recovery |
42
- | `/loop-check` | NO-GO qualification gate — refuse-list + 2-condition test + 30s checklist | Before scheduling a task as an unattended loop | `<task description> [--help]` | Define |
43
- | `/loop-init` | Scaffold `.pi/loops/<name>/` from templates (VISION/STATE/SKILL) | Once a task passes /loop-check | `<name> [--help]` | Define |
44
- | `/loop-review` | Maker/checker gate — verifier subagent runs the gate, emits ACCEPT/REJECT | After a maker run, before ship | `<loop-name> [--help]` | Review |
45
42
 
46
43
  ## When to use what
47
44
 
@@ -57,9 +54,6 @@ Status: /status
57
54
  | "Where am I / what's the state" | `/status` |
58
55
  | Feature done but `/ship` left `.active` dangling | `/close --done` |
59
56
  | Maintenance / dead code sweep | `/gc --dry-run` |
60
- | Qualify a task as an unattended loop (refuse-list + 2-condition test) | `/loop-check "<task>"` (Define) |
61
- | Scaffold a loop after /loop-check returns GO | `/loop-init <name>` (Define) |
62
- | Maker/checker gate on a loop run before shipping | `/loop-review <name>` (Review) |
63
57
 
64
58
  ## Conventions (shared across commands)
65
59
 
@@ -73,6 +67,6 @@ Status: /status
73
67
 
74
68
  ## Related
75
69
 
76
- - `skills/INDEX.md` — task → skill routing (70 skills)
70
+ - `skills/INDEX.md` — task → skill routing (67 skills)
77
71
  - `workflows/INDEX.md` — 6 DAG workflows invoked by commands
78
- - `templates/` — 19 template files (PRD, plan body, state, roadmap, loop-vision, loop-state, orchestrators, etc.)
72
+ - `templates/` — 12 template files (PRD, plan body, state, roadmap, etc.)
@@ -17,17 +17,22 @@ When the agent edits files matching these patterns, the listed skills auto-load.
17
17
 
18
18
  | File pattern | Auto-load skill(s) | Why |
19
19
  |-------------|-------------------|-----|
20
- | `*.ts,*.tsx,*.jsx` | `react-best-practices`, `deep-module-design` | TypeScript/React best practices + structural quality |
20
+ | `*.ts,*.tsx,*.jsx` | `react-best-practices`, `deep-module-design`, `react-compiler` | TypeScript/React best practices + structural quality |
21
+ | `**/actions.ts`, `**/actions/**` | `react-server-actions` | Server Actions + useActionState patterns |
22
+ | `**/app/**/page.tsx`, `**/app/**/layout.tsx` | `nextjs-app-router`, `nextjs-cache` | App Router conventions + caching |
23
+ | `**/stores/**`, `**/store.ts` | `zustand` | Zustand state management patterns |
24
+ | `**/hooks/use-query*.ts`, `**/queries/**` | `tanstack-query` | TanStack Query hooks and patterns |
25
+ | `**/forms/**` with `useForm`, `zodResolver` | `react-hook-form` | React Hook Form + Zod patterns |
21
26
  | `*.swift,*.swiftui` | `swift-concurrency`, `swiftui-expert-skill` | Swift patterns + concurrency safety |
22
27
  | `*.test.*,*.spec.*,__tests__/**` | `test-driven-development`, `testing-anti-patterns` | Test-first discipline + mock hygiene |
23
28
  | `*.sql,migrations/**` | `supabase-postgres-best-practices` | Query performance + RLS |
24
29
  | `.github/workflows/**,Dockerfile,docker-compose*.yml` | `ci-cd-and-automation` | Pipeline design + caching |
25
30
  | `.pi/skills/*/SKILL.md` | `writing-skills` | Skill authoring best practices |
26
- | `.pi/loops/**`,`loop-orchestrator.*`,`loop-guard.ts` | `loop-engineering`, `loop-audit` | Loop design/qualification + readiness scoring |
31
+
27
32
  | `*.css,*.scss,*.less` | `baseline-ui`, `frontend-design`, `design-taste-frontend` | Deslop pass + design system consistency |
28
33
  | `*.tsx,*.jsx` | `baseline-ui`, `frontend-ui-engineering` | Deslop pass + production-quality UI standards |
29
34
  | `*.md,docs/**,ADR*.md` | `documentation-and-adrs` | Doc structure + ADR format |
30
- | `.pi/**/DESIGN.md` | `frontend-design`, `design-taste-frontend` | Project design identity — load aesthetic skills when DESIGN.md is edited |
35
+ | `.pi/**/DESIGN.md` | `frontend-design`, `design-taste-frontend` | Project design identity — load aesthetic skills when DESIGN.md is edited. NOTE: DESIGN.md is no longer auto-injected; load it into context on demand via `/inject-template DESIGN.md` when starting UI work. |
31
36
 
32
37
  ---
33
38
 
@@ -65,10 +70,19 @@ When the user's prompt contains these keywords (case-insensitive), the listed sk
65
70
  | payment, subscription, license, billing, checkout | `polar` |
66
71
  | Figma, design token, mockup, screenshot to code | `figma`, `mockup-to-code` |
67
72
  | Jira, Confluence, Atlassian, issue, ticket | `jira` |
73
+ | v0, v0.sh, v0.dev, AI UI generator, Vercel v0, v0 component, v0 generate | `v0` |
74
+ | shadcn, shadcn/ui, shadcn-ui, shadcn ui, shadcn component, shadcn add | `shadcn-ui` |
75
+ | Server Actions, useActionState, useOptimistic, useFormStatus, 'use server', form action, progressive enhancement | `react-server-actions` |
76
+ | App Router, layout.tsx, page.tsx, parallel routes, intercepting routes, route groups, async params, template.tsx, loading.tsx | `nextjs-app-router` |
77
+ | use cache, cacheLife, cacheTag, revalidateTag, revalidatePath, Next.js cache, connection() | `nextjs-cache` |
78
+ | React Compiler, auto-memoize, babel-plugin-react-compiler, useMemo, useCallback, memoization | `react-compiler` |
79
+ | TanStack Query, React Query, useQuery, useMutation, optimistic update, infinite query, prefetch | `tanstack-query` |
80
+ | Zustand, state management, global state, create store, useShallow, immer, persist, devtools | `zustand` |
81
+ | React Hook Form, useForm, zodResolver, Controller, useFieldArray, form validation, conditional fields | `react-hook-form` |
68
82
  | browser, e2e, screenshot, playwright, chrome | `playwright`, `chrome-devtools`, `browser-testing-with-devtools` |
69
83
  | dependency, package, library, npm, PyPI, source | `opensrc` |
70
84
  | scrape, crawl, webclaw, bot protection, 403, webfetch fail, extract web content, web scraping | `webclaw` |
71
- | loop, unattended loop, nightly triage, loop-readiness, loop-cost, loop-check, loop-review | `loop-engineering`, `loop-audit`, `loop-cost` |
85
+
72
86
  | Swift, iOS, macOS, actor, async/await, Sendable | `swift-concurrency`, `swiftui-expert-skill`, `core-data-expert` |
73
87
 
74
88
  ---
@@ -111,9 +125,7 @@ When the user's prompt contains these keywords (case-insensitive), the listed sk
111
125
  | `dcp-hygiene` | At command/phase closure — compress closed exploratory work-streams via pi-dcp when `compress` is available; no-ops if DCP absent | All | Low |
112
126
  | `memory-system` | Understanding/leveraging pi-hermes-memory — auto-flywheel, tools, commands, when to use memory_search vs vcc_recall | All | Low |
113
127
  | `doubt-driven-development` | In-flight adversarial review of non-trivial decisions before they stand | Build | Medium |
114
- | `loop-engineering` | Designing/qualifying/running unattended coding loops; 2-condition test + VISION/state + confidence-gated action | All | Medium |
115
- | `loop-audit` | Scoring a project's loop-readiness 0-100 + L0/L1/L2/L3; L3 gated on proven run | Review | Low |
116
- | `loop-cost` | Estimating tokens/day + daily cap + early-exit flag before approving a loop budget | Plan | Low |
128
+
117
129
 
118
130
  ### Implementation
119
131
 
@@ -155,7 +167,14 @@ When the user's prompt contains these keywords (case-insensitive), the listed sk
155
167
  | `mockup-to-code` | Converting UI mockups, screenshots, Figma/Sketch designs into code | Build | Medium |
156
168
  | `oklch-color-workflow` | Complete OKLCH color system — syntax, palette generation, contrast, Tailwind v4 | Build | Low |
157
169
  | `production-hardening` | Production hardening — i18n, error states, edge cases, cross-browser | Ship | High |
158
- | `react-best-practices` | Writing, reviewing, or refactoring React/Next.js code for performance | Build | Medium |
170
+ | `react-best-practices` | Writing, reviewing, or refactoring React 19 / Next.js 16 code for performance | Build | Medium |
171
+ | `react-server-actions` | Building forms, mutations, data writes with React 19 Server Actions | Build | Medium |
172
+ | `nextjs-app-router` | Building Next.js App Router pages — layouts, routes, RSC boundaries | Build | Medium |
173
+ | `nextjs-cache` | Next.js 16 caching — `use cache`, cacheLife, cacheTag, revalidation | Build | Medium |
174
+ | `react-compiler` | Enabling, debugging, optimizing with the React Compiler | Build | Low |
175
+ | `tanstack-query` | Data fetching, caching, mutations with TanStack Query v5 | Build | Medium |
176
+ | `zustand` | Global/shared state management with Zustand v5 | Build | Medium |
177
+ | `react-hook-form` | Building forms with React Hook Form v7 + Zod v3 | Build | Medium |
159
178
  | `redesign-existing-projects` | Upgrading an existing website or app's visual design | Build | High |
160
179
  | `ui-craft-principles` | 16 craft principles — concentric radius, optical alignment, interruptible animations | Build | Low |
161
180
  | `ui-quality-audit` | 5-dimension UI quality scoring (0-4) with P0-P3 severity tags | Review | Medium |
@@ -197,6 +216,8 @@ When the user's prompt contains these keywords (case-insensitive), the listed sk
197
216
  | `opensrc` | Understanding how a library works internally, debugging dependency issues | Build | Low |
198
217
  | `pdf-extract` | Extracting text, images, tables, or metadata from PDF files | Build | Low |
199
218
  | `webclaw` | When webfetch returns 403 or bot protection errors | Build | Low |
219
+ | `v0` | Using v0 (v0.app by Vercel) for AI-powered UI generation, prompt engineering, CLI/SDK integration | Build | Medium |
220
+ | `shadcn-ui` | Setting up, configuring, or adding shadcn/ui components — CLI v4, presets, skills, registries | Build | Medium |
200
221
  | `gemini-large-context` | Analyzing large codebases, comparing multiple files exceeding typical context limits | Plan | Low |
201
222
  | `fallow` | Codebase intelligence — quality, dead code, duplication, complexity hotspots | Review | Low |
202
223
 
@@ -227,8 +248,18 @@ Maps user intent to skill(s). `→` = sequential pipeline (execute in order). `+
227
248
  | "I'm stuck" / "not sure what to do" | `behavioral-kernel` + `using-agent-skills` | All | Low |
228
249
  | "which skill to use" / "what skill for" | `using-agent-skills` | Define | Low |
229
250
  | "create UI" / "build component" / "design page" | `frontend-design` + `design-taste-frontend` | Build | Medium |
251
+ | "generate with v0" / "v0 component" / "v0 prompt" / "AI generate UI" | `v0` + `frontend-design` | Build | Medium |
252
+ | "add shadcn components" / "shadcn init" / "setup shadcn" / "shadcn/ui setup" | `shadcn-ui` + `frontend-design` | Build | Medium |
253
+ | "Server Action" / "useActionState" / "useOptimistic" / "'use server'" | `react-server-actions` + `nextjs-app-router` | Build | Medium |
254
+ | "App Router" / "layout.tsx" / "parallel route" / "intercepting route" | `nextjs-app-router` + `react-best-practices` | Build | Medium |
255
+ | "use cache" / "revalidateTag" / "cacheLife" / "Next.js cache" | `nextjs-cache` + `nextjs-app-router` | Build | Medium |
256
+ | "React Compiler" / "auto-memoize" / "useMemo unnecessary" | `react-compiler` + `react-best-practices` | Build | Low |
257
+ | "useQuery" / "useMutation" / "TanStack Query" / "optimistic update" | `tanstack-query` + `zustand` | Build | Medium |
258
+ | "Zustand" / "create store" / "useShallow" / "global state" | `zustand` + `tanstack-query` | Build | Medium |
259
+ | "React Hook Form" / "useForm" / "zodResolver" / "useFieldArray" | `react-hook-form` + `react-server-actions` | Build | Medium |
230
260
  | "deploy to Cloudflare" | `cloudflare` | Ship | High |
231
261
  | "deploy to Vercel" | `vercel-deploy-claimable` | Ship | High |
262
+ | "animate" / "animation" / "motion" / "framer" / "transition" | `frontend-design` (references/animation/) | Build | Low |
232
263
  | "set up database" / "Supabase" | `supabase` + `supabase-postgres-best-practices` | Build | High |
233
264
  | "add logging" / "monitoring" / "observability" | `observability-and-instrumentation` | Ship | Medium |
234
265
  | "optimize context" / "agent quality degraded" / "too many tokens" | `context-engineering` | All | Low |
@@ -16,7 +16,7 @@ description: "Use at command/phase closure points to compress closed exploratory
16
16
  - The `compress` tool is not registered (DCP extension not installed, or `compress.permission: "deny"`) — see No-op clause below.
17
17
  - The work-stream is still in-flight or spans your most recent turn — DCP turn protection (last 3 turns) already refuses these; don't try.
18
18
  - The user just asked about the content you'd be compressing — they still need it verbatim.
19
- - The command is read-only/scaffold and produced almost no tool output (`/status`, `/close`, `/loop-init`, `/loop-check`, `/loop-review`) — compressing near-empty streams wastes more tokens than it saves.
19
+ - The command is read-only/scaffold and produced almost no tool output (`/status`, `/close`) — compressing near-empty streams wastes more tokens than it saves.
20
20
  - Inside orchestrator workflows' phase prompts — subagents carry their own context; only the orchestrator's accumulated summaries matter, and those are bounded by "Keep under N words" per prompt.
21
21
 
22
22
  ## Core Principle
@@ -43,7 +43,7 @@ description: MUST load when building any web UI with React-based frameworks —
43
43
 
44
44
  Search: `@theme`, `@container`, `OKLCH`, `mask-`, `text-shadow`
45
45
 
46
- ### shadcn/ui (CLI v3.6)
46
+ ### shadcn/ui (CLI v4.11)
47
47
 
48
48
  - `./references/shadcn/setup.md` - Installation, visual styles, component list
49
49
  - `./references/shadcn/core-components.md` - Button, Card, Dialog, Select, Tabs, Toast
@@ -1,13 +1,13 @@
1
1
  # Motion Advanced
2
2
 
3
- Scroll, orchestration, TypeScript, performance.
3
+ Scroll, orchestration, TypeScript, AnimateView, performance.
4
4
 
5
5
  ## Scroll Animations
6
6
 
7
7
  ```tsx
8
8
  import { motion, useScroll, useTransform } from 'motion/react';
9
9
 
10
- // Scroll progress
10
+ // Scroll progress (GPU-accelerated via ScrollTimeline API since v12.32)
11
11
  const { scrollYProgress } = useScroll();
12
12
  const opacity = useTransform(scrollYProgress, [0, 1], [1, 0]);
13
13
 
@@ -36,7 +36,7 @@ const scale = useTransform(scrollYProgress, [0, 0.5, 1], [0.8, 1, 0.8]);
36
36
  ## AnimatePresence Modes
37
37
 
38
38
  ```tsx
39
- // Wait for exit before enter
39
+ // Wait for exit before enter (recommended for page transitions)
40
40
  <AnimatePresence mode="wait">
41
41
  <motion.div key={currentPage} />
42
42
  </AnimatePresence>
@@ -50,6 +50,37 @@ const scale = useTransform(scrollYProgress, [0, 0.5, 1], [0.8, 1, 0.8]);
50
50
  <AnimatePresence mode="sync" />
51
51
  ```
52
52
 
53
+ ## AnimateView (New — Motion+ Early Access)
54
+
55
+ View Transitions wrapper for React. Enter/exit/update/share animations for page transitions:
56
+
57
+ ```tsx
58
+ import { AnimateView } from 'motion/react'
59
+
60
+ <AnimateView>
61
+ <motion.div
62
+ animate={{ opacity: 1, scale: 1 }}
63
+ initial={{ opacity: 0, scale: 0.95 }}
64
+ />
65
+ </AnimateView>
66
+ ```
67
+
68
+ Built on React 19.2 `ViewTransition` component. Works alongside Next.js 16 `experimental.viewTransition`.
69
+
70
+ ## arc() — Curved Motion Paths (v12.40+)
71
+
72
+ ```tsx
73
+ import { arc } from 'motion/react'
74
+
75
+ <motion.div
76
+ animate={{
77
+ x: 200,
78
+ y: -120,
79
+ transition: { path: arc() }
80
+ }}
81
+ />
82
+ ```
83
+
53
84
  ## Orchestration
54
85
 
55
86
  ```tsx
@@ -157,6 +188,24 @@ const prefersReduced = useReducedMotion();
157
188
 
158
189
  // Use layoutRoot to isolate layout calculations
159
190
  <motion.div layoutRoot />
191
+
192
+ // Axis-locked layout (v12.35+) — cheaper than full layout
193
+ <motion.div layout="x" />
194
+
195
+ // Custom anchor point (v12.38+)
196
+ <motion.div layoutAnchor={{ x: 0.5, y: 0.5 }} />
197
+ ```
198
+
199
+ ## CSS Color Support (v12.35+)
200
+
201
+ Motion now supports modern CSS color formats:
202
+ - `oklch()`, `oklab()`, `lab()`, `lch()`
203
+ - `color-mix()`, `light-dark()`
204
+
205
+ ```tsx
206
+ <motion.div
207
+ animate={{ backgroundColor: 'oklch(0.65 0.22 250)' }}
208
+ />
160
209
  ```
161
210
 
162
211
  ## Common Patterns
@@ -171,18 +220,28 @@ const prefersReduced = useReducedMotion();
171
220
  />
172
221
  ```
173
222
 
174
- ### Page transitions
223
+ ### Page transitions (Next.js App Router)
175
224
  ```tsx
176
- <AnimatePresence mode="wait">
177
- <motion.main
178
- key={pathname}
179
- initial={{ opacity: 0, x: 20 }}
180
- animate={{ opacity: 1, x: 0 }}
181
- exit={{ opacity: 0, x: -20 }}
182
- >
183
- {children}
184
- </motion.main>
185
- </AnimatePresence>
225
+ // app/template.tsx
226
+ 'use client'
227
+ import { AnimatePresence, motion } from 'motion/react'
228
+ import { usePathname } from 'next/navigation'
229
+
230
+ export default function Template({ children }) {
231
+ const pathname = usePathname()
232
+ return (
233
+ <AnimatePresence mode="wait" initial={false}>
234
+ <motion.main
235
+ key={pathname}
236
+ initial={{ opacity: 0, x: 20 }}
237
+ animate={{ opacity: 1, x: 0 }}
238
+ exit={{ opacity: 0, x: -20 }}
239
+ >
240
+ {children}
241
+ </motion.main>
242
+ </AnimatePresence>
243
+ )
244
+ }
186
245
  ```
187
246
 
188
247
  ### Expandable card
@@ -212,13 +271,27 @@ anime.js v4 still appropriate for:
212
271
  - Non-React projects
213
272
 
214
273
  ```javascript
215
- // anime.js for SVG morphing
216
274
  import { animate, svg } from 'animejs';
217
275
  animate('#path1', { d: svg.morphTo('#path2'), duration: 1 });
218
276
  ```
219
277
 
278
+ ## Library Comparison (2026)
279
+
280
+ | Library | Bundle | React DX | Scroll | Gestures | Layout Anim |
281
+ |---------|--------|----------|--------|----------|-------------|
282
+ | **Motion** | ~85KB | 🏆 Best | Built-in | Built-in | Built-in |
283
+ | GSAP | ~78KB | Imperative | ScrollTrigger | Draggable | Flip plugin |
284
+ | React Spring | ~45KB | Good | External | ❌ | ❌ |
285
+ | Anime.js | ~52KB | Imperative | External | ❌ | ❌ |
286
+ | TailwindCSS Motion | ~5KB | Good | Built-in | ❌ | ❌ |
287
+
288
+ **Verdict**: Motion for React-first projects with complex interactions. GSAP for marketing sites with complex timelines. React Spring for physics-driven natural motion. Anime.js for SVG path animations.
289
+
220
290
  ## Installation
221
291
 
222
292
  ```bash
223
293
  npm install motion
294
+ # or migrate from framer-motion:
295
+ npm uninstall framer-motion && npm install motion
296
+ # swap imports: "framer-motion" → "motion/react"
224
297
  ```
@@ -1,6 +1,9 @@
1
1
  # Motion Core (motion/react)
2
2
 
3
- **Import**: `import { motion, AnimatePresence } from 'motion/react'`
3
+ **Package**: `motion` (v12.40.0). Formerly "framer-motion".
4
+ **Import**: `import { motion, AnimatePresence, useScroll, useTransform } from 'motion/react'`
5
+
6
+ Framer Motion rebranded to **Motion** in November 2024. Both `motion` and `framer-motion` packages published in lockstep. New projects use `motion`. No breaking changes in v12 for React.
4
7
 
5
8
  ## Motion Principles
6
9
 
@@ -8,6 +11,8 @@
8
11
  - Use motion to explain state change and hierarchy
9
12
  - Prefer subtle distance (`8-16px`) and opacity shifts
10
13
  - Use consistent timing/easing system across the app
14
+ - Let Tailwind handle static styles; Motion handles behavior
15
+ - **Remove `transition-*` Tailwind classes from motion elements** — they conflict
11
16
 
12
17
  ## Timing System
13
18
 
@@ -19,6 +24,7 @@
19
24
  | Large entrances | 500-800ms |
20
25
 
21
26
  **Rule**: exit duration = ~75% of enter duration.
27
+ **Never exceed 600ms for UI responsiveness.**
22
28
 
23
29
  ## Easing System
24
30
 
@@ -29,20 +35,20 @@ const EASING_ENTER = [0.16, 1, 0.3, 1];
29
35
  const EASING_EXIT = [0.4, 0, 1, 1];
30
36
  ```
31
37
 
32
- Avoid bounce/elastic easings for product UI.
38
+ Avoid bounce/elastic easings for product UI. Motion's hybrid engine runs animations natively via Web Animations API (WAAPI) and ScrollTimeline for 120fps GPU performance, falling back to JS only for spring physics and gestures.
33
39
 
34
40
  ## Performance Rules
35
41
 
36
42
  Animate only compositor-friendly properties:
37
43
 
38
- - `transform`
44
+ - `transform` (x, y, scale, rotate, skew)
39
45
  - `opacity`
40
46
 
41
47
  Avoid animating:
42
48
 
43
- - `width`, `height`
44
- - `top`, `left`
45
- - `margin`, `padding`
49
+ - `width`, `height` — triggers layout recalculation
50
+ - `top`, `left` — use `x`/`y` instead
51
+ - `margin`, `padding`, `border`
46
52
 
47
53
  ## Basic Pattern
48
54
 
@@ -54,6 +60,101 @@ Avoid animating:
54
60
  />
55
61
  ```
56
62
 
63
+ ## React 19 + Next.js 15/16
64
+
65
+ ### Page Transitions (App Router)
66
+
67
+ **Critical**: Use `template.tsx`, NOT `layout.tsx`. Layout persists across routes and never remounts.
68
+
69
+ ```tsx
70
+ // app/template.tsx
71
+ 'use client'
72
+
73
+ import { AnimatePresence, motion } from 'motion/react'
74
+ import { usePathname } from 'next/navigation'
75
+
76
+ export default function Template({ children }: { children: React.ReactNode }) {
77
+ const pathname = usePathname()
78
+ return (
79
+ <AnimatePresence mode="wait" initial={false}>
80
+ <motion.div
81
+ key={pathname}
82
+ initial={{ opacity: 0, y: 8 }}
83
+ animate={{ opacity: 1, y: 0 }}
84
+ exit={{ opacity: 0, y: -8 }}
85
+ transition={{ duration: 0.18, ease: 'easeInOut' }}
86
+ style={{ minHeight: 'var(--page-min-height, 100dvh)' }}
87
+ >
88
+ {children}
89
+ </motion.div>
90
+ </AnimatePresence>
91
+ )
92
+ }
93
+ ```
94
+
95
+ ### Dynamic Import (Performance)
96
+
97
+ ```tsx
98
+ import dynamic from 'next/dynamic'
99
+
100
+ const AnimatedWrapper = dynamic(() => import('@/components/animated-wrapper'), {
101
+ ssr: false,
102
+ loading: ({ children }) => <>{children}</>,
103
+ })
104
+ ```
105
+
106
+ ### React 19.2 View Transitions
107
+
108
+ Next.js 16 + React 19.2 support native View Transitions via `experimental.viewTransition: true`. Motion's `AnimateView` (premium) builds on this.
109
+
110
+ ## Integration with shadcn/ui
111
+
112
+ **Architecture**: shadcn/ui = structure + accessibility. Motion = behavior + animation. Wrap/extend shadcn components — don't replace.
113
+
114
+ ```
115
+ src/
116
+ ├── components/
117
+ │ ├── ui/ # shadcn generated (untouched)
118
+ │ └── animated/ # Motion-wrapped shadcn components
119
+ │ ├── AnimatedButton.tsx
120
+ │ ├── AnimatedDialog.tsx
121
+ │ └── ...
122
+ └── lib/
123
+ └── animations.ts # Shared variants & transition configs
124
+ ```
125
+
126
+ ### Shared Variants Pattern
127
+
128
+ ```ts
129
+ // lib/animations.ts
130
+ import type { Variants, Transition } from 'motion/react'
131
+
132
+ export const fadeIn: Variants = {
133
+ initial: { opacity: 0 },
134
+ animate: { opacity: 1 },
135
+ exit: { opacity: 0 },
136
+ }
137
+
138
+ export const slideUp: Variants = {
139
+ initial: { opacity: 0, y: 20 },
140
+ animate: { opacity: 1, y: 0 },
141
+ exit: { opacity: 0, y: 20 },
142
+ }
143
+
144
+ export const spring: Transition = {
145
+ type: 'spring',
146
+ stiffness: 300,
147
+ damping: 25,
148
+ }
149
+ ```
150
+
151
+ ### Installation Order
152
+
153
+ 1. `npx shadcn init` + add components
154
+ 2. `npm install motion`
155
+ 3. Create `lib/animations.ts` for shared variants
156
+ 4. Create `components/animated/` directory for wrapped components
157
+
57
158
  ## Variants Pattern (Recommended)
58
159
 
59
160
  ```tsx
@@ -69,8 +170,6 @@ const card = {
69
170
  <motion.div variants={card} initial="hidden" animate="visible" />
70
171
  ```
71
172
 
72
- Use variants for shared timing and maintainability.
73
-
74
173
  ## Exit Animations (AnimatePresence)
75
174
 
76
175
  ```tsx
@@ -87,7 +186,7 @@ Use variants for shared timing and maintainability.
87
186
  </AnimatePresence>
88
187
  ```
89
188
 
90
- Always provide stable `key` values for exiting elements.
189
+ Always provide stable `key` values. Use `mode="wait"` to prevent overlapping DOM elements.
91
190
 
92
191
  ## Stagger Patterns
93
192
 
@@ -123,6 +222,9 @@ Use `layout` for reordering and size changes. Add spring only when needed:
123
222
  <motion.div layout transition={{ type: 'spring', stiffness: 320, damping: 28 }} />
124
223
  ```
125
224
 
225
+ **New (v12.35+)**: Axis-locked layout: `layout="x"` or `layout="y"`.
226
+ **New (v12.38+)**: Custom anchor: `layoutAnchor={{ x: 0.5, y: 0.5 }}`.
227
+
126
228
  ## Gestures
127
229
 
128
230
  ```tsx
@@ -133,7 +235,7 @@ Use `layout` for reordering and size changes. Add spring only when needed:
133
235
  />
134
236
  ```
135
237
 
136
- Keep gesture amplitudes subtle (`0.98-1.03`).
238
+ Keep gesture amplitudes subtle (`0.98-1.03`). Available: `whileHover`, `whileTap`, `whileFocus`, `whileDrag`, `whileInView`.
137
239
 
138
240
  ## Height Expand/Collapse (No height animation)
139
241
 
@@ -168,14 +270,47 @@ Use CSS grid technique:
168
270
  }
169
271
  ```
170
272
 
171
- For motion/react, switch spatial movement to opacity-only when reduced motion is enabled.
273
+ For motion/react, use `useReducedMotion()`:
274
+
275
+ ```tsx
276
+ import { useReducedMotion } from 'motion/react'
277
+
278
+ const prefersReduced = useReducedMotion()
279
+
280
+ <motion.div
281
+ animate={prefersReduced ? {} : { scale: 1.1 }}
282
+ />
283
+ ```
284
+
285
+ ## Motion AI Kit
286
+
287
+ Official Motion AI tools (premium, Motion+ required):
288
+ ```bash
289
+ npx motion-ai # Install MCP server + skills for Claude Code, Cursor, Windsurf, etc.
290
+ ```
291
+
292
+ Provides: 400+ premium examples, MotionScore runtime profiling, CSS spring generation, transition editing.
293
+
294
+ ## Common Pitfalls
295
+
296
+ | Pitfall | Fix |
297
+ |---------|-----|
298
+ | `layout.tsx` for AnimatePresence (CLS) | Use `template.tsx` with `mode="wait"` |
299
+ | `transition-*` classes on motion elements | Remove Tailwind transition classes |
300
+ | Animating `width`/`height` | Use `scaleX`/`scaleY` or grid technique |
301
+ | Missing `use client` in Next.js | Extract animation to client component |
302
+ | `mode="sync"` with page transitions | Use `mode="wait"` to prevent overlap |
303
+ | Duration > 600ms for UI | Cap at 600ms; reserve long durations for storytelling |
172
304
 
173
305
  ## Quick Checklist
174
306
 
175
- - [ ] Uses `motion/react` import
307
+ - [ ] Uses `motion/react` import (not `framer-motion`)
176
308
  - [ ] Timing follows 100/300/500ms system
177
309
  - [ ] Exponential easing, no bounce/elastic
178
310
  - [ ] Animates only `transform` and `opacity`
179
311
  - [ ] Uses `AnimatePresence` for exit states
180
- - [ ] Includes reduced motion support
312
+ - [ ] Includes reduced motion support (CSS + `useReducedMotion()`)
181
313
  - [ ] Stagger windows stay under 500ms
314
+ - [ ] Next.js: uses `template.tsx` not `layout.tsx`
315
+ - [ ] No `transition-*` classes on motion elements
316
+ - [ ] shadcn/ui: animated components in `components/animated/`