niahere 0.2.61 → 0.2.63

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 (186) hide show
  1. package/defaults/memory-promoter.md +99 -0
  2. package/defaults/self/staging.md +48 -0
  3. package/package.json +7 -3
  4. package/skills/code-review/pr-review.md +14 -1
  5. package/skills/cro/page.md +22 -0
  6. package/skills/frontend-design/SKILL.md +7 -3
  7. package/skills/frontend-design/building.md +17 -2
  8. package/skills/qa/SKILL.md +108 -72
  9. package/skills/userinterface-wiki/AGENTS.md +3749 -0
  10. package/skills/userinterface-wiki/SKILL.md +253 -0
  11. package/skills/userinterface-wiki/metadata.json +26 -0
  12. package/skills/userinterface-wiki/rules/_sections.md +66 -0
  13. package/skills/userinterface-wiki/rules/_template.md +24 -0
  14. package/skills/userinterface-wiki/rules/a11y-reduced-motion-check.md +30 -0
  15. package/skills/userinterface-wiki/rules/a11y-toggle-setting.md +30 -0
  16. package/skills/userinterface-wiki/rules/a11y-visual-equivalent.md +36 -0
  17. package/skills/userinterface-wiki/rules/a11y-volume-control.md +28 -0
  18. package/skills/userinterface-wiki/rules/appropriate-confirmations-only.md +19 -0
  19. package/skills/userinterface-wiki/rules/appropriate-errors-warnings.md +18 -0
  20. package/skills/userinterface-wiki/rules/appropriate-no-decorative.md +21 -0
  21. package/skills/userinterface-wiki/rules/appropriate-no-high-frequency.md +28 -0
  22. package/skills/userinterface-wiki/rules/appropriate-no-punishing.md +27 -0
  23. package/skills/userinterface-wiki/rules/container-callback-ref.md +31 -0
  24. package/skills/userinterface-wiki/rules/container-guard-initial-zero.md +25 -0
  25. package/skills/userinterface-wiki/rules/container-no-excessive-use.md +13 -0
  26. package/skills/userinterface-wiki/rules/container-overflow-hidden.md +25 -0
  27. package/skills/userinterface-wiki/rules/container-transition-delay.md +21 -0
  28. package/skills/userinterface-wiki/rules/container-two-div-pattern.md +35 -0
  29. package/skills/userinterface-wiki/rules/container-use-resize-observer.md +48 -0
  30. package/skills/userinterface-wiki/rules/context-cleanup-nodes.md +25 -0
  31. package/skills/userinterface-wiki/rules/context-resume-suspended.md +28 -0
  32. package/skills/userinterface-wiki/rules/context-reuse-single.md +30 -0
  33. package/skills/userinterface-wiki/rules/design-filter-for-character.md +25 -0
  34. package/skills/userinterface-wiki/rules/design-noise-for-percussion.md +26 -0
  35. package/skills/userinterface-wiki/rules/design-oscillator-for-tonal.md +22 -0
  36. package/skills/userinterface-wiki/rules/duration-max-300ms.md +21 -0
  37. package/skills/userinterface-wiki/rules/duration-press-hover.md +21 -0
  38. package/skills/userinterface-wiki/rules/duration-shorten-before-curve.md +21 -0
  39. package/skills/userinterface-wiki/rules/duration-small-state.md +15 -0
  40. package/skills/userinterface-wiki/rules/easing-entrance-ease-out.md +21 -0
  41. package/skills/userinterface-wiki/rules/easing-exit-ease-in.md +21 -0
  42. package/skills/userinterface-wiki/rules/easing-for-state-change.md +27 -0
  43. package/skills/userinterface-wiki/rules/easing-linear-only-progress.md +21 -0
  44. package/skills/userinterface-wiki/rules/easing-natural-decay.md +22 -0
  45. package/skills/userinterface-wiki/rules/easing-no-linear-motion.md +22 -0
  46. package/skills/userinterface-wiki/rules/easing-transition-ease-in-out.md +15 -0
  47. package/skills/userinterface-wiki/rules/envelope-exponential-decay.md +21 -0
  48. package/skills/userinterface-wiki/rules/envelope-no-zero-target.md +21 -0
  49. package/skills/userinterface-wiki/rules/envelope-set-initial-value.md +22 -0
  50. package/skills/userinterface-wiki/rules/exit-key-required.md +29 -0
  51. package/skills/userinterface-wiki/rules/exit-matches-initial.md +29 -0
  52. package/skills/userinterface-wiki/rules/exit-prop-required.md +33 -0
  53. package/skills/userinterface-wiki/rules/exit-requires-wrapper.md +27 -0
  54. package/skills/userinterface-wiki/rules/impl-default-subtle.md +21 -0
  55. package/skills/userinterface-wiki/rules/impl-preload-audio.md +34 -0
  56. package/skills/userinterface-wiki/rules/impl-reset-current-time.md +26 -0
  57. package/skills/userinterface-wiki/rules/mode-pop-layout-for-lists.md +25 -0
  58. package/skills/userinterface-wiki/rules/mode-sync-layout-conflict.md +29 -0
  59. package/skills/userinterface-wiki/rules/mode-wait-doubles-duration.md +25 -0
  60. package/skills/userinterface-wiki/rules/morphing-aria-hidden.md +21 -0
  61. package/skills/userinterface-wiki/rules/morphing-consistent-viewbox.md +23 -0
  62. package/skills/userinterface-wiki/rules/morphing-group-variants.md +33 -0
  63. package/skills/userinterface-wiki/rules/morphing-jump-non-grouped.md +29 -0
  64. package/skills/userinterface-wiki/rules/morphing-reduced-motion.md +28 -0
  65. package/skills/userinterface-wiki/rules/morphing-spring-rotation.md +23 -0
  66. package/skills/userinterface-wiki/rules/morphing-strokelinecap-round.md +21 -0
  67. package/skills/userinterface-wiki/rules/morphing-three-lines.md +32 -0
  68. package/skills/userinterface-wiki/rules/morphing-use-collapsed.md +33 -0
  69. package/skills/userinterface-wiki/rules/native-backdrop-styling.md +27 -0
  70. package/skills/userinterface-wiki/rules/native-placeholder-styling.md +27 -0
  71. package/skills/userinterface-wiki/rules/native-selection-styling.md +18 -0
  72. package/skills/userinterface-wiki/rules/nested-consistent-timing.md +25 -0
  73. package/skills/userinterface-wiki/rules/nested-propagate-required.md +41 -0
  74. package/skills/userinterface-wiki/rules/none-context-menu-entrance.md +25 -0
  75. package/skills/userinterface-wiki/rules/none-high-frequency.md +29 -0
  76. package/skills/userinterface-wiki/rules/none-keyboard-navigation.md +32 -0
  77. package/skills/userinterface-wiki/rules/param-click-duration.md +21 -0
  78. package/skills/userinterface-wiki/rules/param-filter-frequency-range.md +21 -0
  79. package/skills/userinterface-wiki/rules/param-q-value-range.md +21 -0
  80. package/skills/userinterface-wiki/rules/param-reasonable-gain.md +21 -0
  81. package/skills/userinterface-wiki/rules/physics-active-state.md +23 -0
  82. package/skills/userinterface-wiki/rules/physics-no-excessive-stagger.md +22 -0
  83. package/skills/userinterface-wiki/rules/physics-spring-for-overshoot.md +23 -0
  84. package/skills/userinterface-wiki/rules/physics-subtle-deformation.md +22 -0
  85. package/skills/userinterface-wiki/rules/prefetch-hit-slop.md +27 -0
  86. package/skills/userinterface-wiki/rules/prefetch-keyboard-tab.md +19 -0
  87. package/skills/userinterface-wiki/rules/prefetch-not-everything.md +22 -0
  88. package/skills/userinterface-wiki/rules/prefetch-touch-fallback.md +34 -0
  89. package/skills/userinterface-wiki/rules/prefetch-trajectory-over-hover.md +32 -0
  90. package/skills/userinterface-wiki/rules/prefetch-use-selectively.md +13 -0
  91. package/skills/userinterface-wiki/rules/presence-disable-interactions.md +31 -0
  92. package/skills/userinterface-wiki/rules/presence-hook-in-child.md +31 -0
  93. package/skills/userinterface-wiki/rules/presence-safe-to-remove.md +37 -0
  94. package/skills/userinterface-wiki/rules/pseudo-content-required.md +28 -0
  95. package/skills/userinterface-wiki/rules/pseudo-first-line-styling.md +27 -0
  96. package/skills/userinterface-wiki/rules/pseudo-hit-target-expansion.md +31 -0
  97. package/skills/userinterface-wiki/rules/pseudo-marker-styling.md +28 -0
  98. package/skills/userinterface-wiki/rules/pseudo-over-dom-node.md +32 -0
  99. package/skills/userinterface-wiki/rules/pseudo-position-relative-parent.md +33 -0
  100. package/skills/userinterface-wiki/rules/pseudo-z-index-layering.md +37 -0
  101. package/skills/userinterface-wiki/rules/spring-for-gestures.md +27 -0
  102. package/skills/userinterface-wiki/rules/spring-for-interruptible.md +27 -0
  103. package/skills/userinterface-wiki/rules/spring-params-balanced.md +29 -0
  104. package/skills/userinterface-wiki/rules/spring-preserves-velocity.md +28 -0
  105. package/skills/userinterface-wiki/rules/staging-dim-background.md +22 -0
  106. package/skills/userinterface-wiki/rules/staging-one-focal-point.md +24 -0
  107. package/skills/userinterface-wiki/rules/staging-z-index-hierarchy.md +22 -0
  108. package/skills/userinterface-wiki/rules/timing-consistent.md +24 -0
  109. package/skills/userinterface-wiki/rules/timing-no-entrance-context-menu.md +22 -0
  110. package/skills/userinterface-wiki/rules/timing-under-300ms.md +22 -0
  111. package/skills/userinterface-wiki/rules/transition-name-cleanup.md +28 -0
  112. package/skills/userinterface-wiki/rules/transition-name-required.md +27 -0
  113. package/skills/userinterface-wiki/rules/transition-name-unique.md +24 -0
  114. package/skills/userinterface-wiki/rules/transition-over-js-library.md +32 -0
  115. package/skills/userinterface-wiki/rules/transition-style-pseudo-elements.md +24 -0
  116. package/skills/userinterface-wiki/rules/type-antialiased-on-retina.md +18 -0
  117. package/skills/userinterface-wiki/rules/type-disambiguation-stylistic-set.md +15 -0
  118. package/skills/userinterface-wiki/rules/type-font-display-swap.md +28 -0
  119. package/skills/userinterface-wiki/rules/type-justify-with-hyphens.md +24 -0
  120. package/skills/userinterface-wiki/rules/type-letter-spacing-uppercase.md +28 -0
  121. package/skills/userinterface-wiki/rules/type-no-font-synthesis.md +18 -0
  122. package/skills/userinterface-wiki/rules/type-oldstyle-nums-for-prose.md +21 -0
  123. package/skills/userinterface-wiki/rules/type-opentype-contextual-alternates.md +15 -0
  124. package/skills/userinterface-wiki/rules/type-optical-sizing-auto.md +25 -0
  125. package/skills/userinterface-wiki/rules/type-proper-fractions.md +15 -0
  126. package/skills/userinterface-wiki/rules/type-slashed-zero.md +17 -0
  127. package/skills/userinterface-wiki/rules/type-tabular-nums-for-data.md +21 -0
  128. package/skills/userinterface-wiki/rules/type-text-wrap-balance-headings.md +21 -0
  129. package/skills/userinterface-wiki/rules/type-text-wrap-pretty.md +16 -0
  130. package/skills/userinterface-wiki/rules/type-underline-offset.md +25 -0
  131. package/skills/userinterface-wiki/rules/type-variable-weight-continuous.md +23 -0
  132. package/skills/userinterface-wiki/rules/ux-aesthetic-usability.md +32 -0
  133. package/skills/userinterface-wiki/rules/ux-cognitive-load-reduce.md +49 -0
  134. package/skills/userinterface-wiki/rules/ux-common-region-boundaries.md +50 -0
  135. package/skills/userinterface-wiki/rules/ux-doherty-perceived-speed.md +29 -0
  136. package/skills/userinterface-wiki/rules/ux-doherty-under-400ms.md +30 -0
  137. package/skills/userinterface-wiki/rules/ux-fitts-hit-area.md +32 -0
  138. package/skills/userinterface-wiki/rules/ux-fitts-target-size.md +31 -0
  139. package/skills/userinterface-wiki/rules/ux-goal-gradient-progress.md +33 -0
  140. package/skills/userinterface-wiki/rules/ux-hicks-minimize-choices.md +45 -0
  141. package/skills/userinterface-wiki/rules/ux-jakobs-familiar-patterns.md +37 -0
  142. package/skills/userinterface-wiki/rules/ux-millers-chunking.md +23 -0
  143. package/skills/userinterface-wiki/rules/ux-pareto-prioritize-features.md +36 -0
  144. package/skills/userinterface-wiki/rules/ux-peak-end-finish-strong.md +35 -0
  145. package/skills/userinterface-wiki/rules/ux-postels-accept-messy-input.md +45 -0
  146. package/skills/userinterface-wiki/rules/ux-pragnanz-simplify.md +33 -0
  147. package/skills/userinterface-wiki/rules/ux-progressive-disclosure.md +41 -0
  148. package/skills/userinterface-wiki/rules/ux-proximity-grouping.md +38 -0
  149. package/skills/userinterface-wiki/rules/ux-serial-position.md +31 -0
  150. package/skills/userinterface-wiki/rules/ux-similarity-consistency.md +35 -0
  151. package/skills/userinterface-wiki/rules/ux-teslers-complexity.md +28 -0
  152. package/skills/userinterface-wiki/rules/ux-uniform-connectedness.md +43 -0
  153. package/skills/userinterface-wiki/rules/ux-von-restorff-emphasis.md +29 -0
  154. package/skills/userinterface-wiki/rules/ux-zeigarnik-show-incomplete.md +36 -0
  155. package/skills/userinterface-wiki/rules/visual-animate-shadow-pseudo.md +49 -0
  156. package/skills/userinterface-wiki/rules/visual-border-alpha-colors.md +25 -0
  157. package/skills/userinterface-wiki/rules/visual-button-shadow-anatomy.md +49 -0
  158. package/skills/userinterface-wiki/rules/visual-concentric-radius.md +40 -0
  159. package/skills/userinterface-wiki/rules/visual-consistent-spacing-scale.md +35 -0
  160. package/skills/userinterface-wiki/rules/visual-layered-shadows.md +30 -0
  161. package/skills/userinterface-wiki/rules/visual-no-pure-black-shadow.md +25 -0
  162. package/skills/userinterface-wiki/rules/visual-shadow-direction.md +25 -0
  163. package/skills/userinterface-wiki/rules/visual-shadow-matches-elevation.md +23 -0
  164. package/skills/userinterface-wiki/rules/weight-duration-matches-action.md +29 -0
  165. package/skills/userinterface-wiki/rules/weight-match-action.md +32 -0
  166. package/src/cli/index.ts +23 -73
  167. package/src/cli/job.ts +25 -92
  168. package/src/cli/status.ts +17 -9
  169. package/src/commands/init.ts +1 -0
  170. package/src/commands/validate.ts +12 -10
  171. package/src/core/agents.ts +6 -19
  172. package/src/core/consolidator.ts +97 -91
  173. package/src/core/daemon.ts +71 -43
  174. package/src/core/finalizer.ts +31 -3
  175. package/src/core/health.ts +5 -17
  176. package/src/core/runner.ts +8 -44
  177. package/src/core/scheduler.ts +12 -49
  178. package/src/core/skills.ts +4 -11
  179. package/src/core/summarizer.ts +7 -21
  180. package/src/db/connection.ts +0 -11
  181. package/src/db/models/job.ts +23 -22
  182. package/src/db/with-db.ts +11 -0
  183. package/src/mcp/server.ts +1 -1
  184. package/src/prompts/environment.md +44 -41
  185. package/src/utils/pid.ts +44 -0
  186. package/src/utils/schedule.ts +39 -0
@@ -0,0 +1,32 @@
1
+ ---
2
+ title: No Animation for Keyboard Navigation
3
+ impact: MEDIUM
4
+ tags: none, keyboard, a11y
5
+ ---
6
+
7
+ ## No Animation for Keyboard Navigation
8
+
9
+ Keyboard navigation should be instant, no animation.
10
+
11
+ **Incorrect (animated focus):**
12
+
13
+ ```tsx
14
+ function Menu() {
15
+ return items.map(item => (
16
+ <motion.li
17
+ whileFocus={{ scale: 1.05 }}
18
+ transition={{ duration: 0.2 }}
19
+ />
20
+ ));
21
+ }
22
+ ```
23
+
24
+ **Correct (CSS focus-visible only):**
25
+
26
+ ```tsx
27
+ function Menu() {
28
+ return items.map(item => (
29
+ <li className={styles.menuItem} />
30
+ ));
31
+ }
32
+ ```
@@ -0,0 +1,21 @@
1
+ ---
2
+ title: Click Duration 5-15ms
3
+ impact: MEDIUM
4
+ tags: param, click, duration
5
+ ---
6
+
7
+ ## Click Duration 5-15ms
8
+
9
+ Click/tap sounds should be 5-15ms duration.
10
+
11
+ **Incorrect (too long):**
12
+
13
+ ```ts
14
+ const buffer = ctx.createBuffer(1, ctx.sampleRate * 0.1, ctx.sampleRate);
15
+ ```
16
+
17
+ **Correct (appropriate duration):**
18
+
19
+ ```ts
20
+ const buffer = ctx.createBuffer(1, ctx.sampleRate * 0.008, ctx.sampleRate);
21
+ ```
@@ -0,0 +1,21 @@
1
+ ---
2
+ title: Click Filter 3000-6000Hz
3
+ impact: LOW
4
+ tags: param, filter, frequency
5
+ ---
6
+
7
+ ## Click Filter 3000-6000Hz
8
+
9
+ Bandpass filter for clicks should be 3000-6000Hz.
10
+
11
+ **Incorrect (too low):**
12
+
13
+ ```ts
14
+ filter.frequency.value = 500;
15
+ ```
16
+
17
+ **Correct (crisp range):**
18
+
19
+ ```ts
20
+ filter.frequency.value = 4000;
21
+ ```
@@ -0,0 +1,21 @@
1
+ ---
2
+ title: Filter Q Value 2-5
3
+ impact: LOW
4
+ tags: param, q-value, filter
5
+ ---
6
+
7
+ ## Filter Q Value 2-5
8
+
9
+ Filter Q for clicks should be 2-5 for focused but not harsh sound.
10
+
11
+ **Incorrect (too resonant):**
12
+
13
+ ```ts
14
+ filter.Q.value = 15;
15
+ ```
16
+
17
+ **Correct (balanced Q):**
18
+
19
+ ```ts
20
+ filter.Q.value = 3;
21
+ ```
@@ -0,0 +1,21 @@
1
+ ---
2
+ title: Gain Under 1.0
3
+ impact: MEDIUM
4
+ tags: param, gain, clipping
5
+ ---
6
+
7
+ ## Gain Under 1.0
8
+
9
+ Gain values should not exceed 1.0 to prevent clipping.
10
+
11
+ **Incorrect (clipping):**
12
+
13
+ ```ts
14
+ gain.gain.setValueAtTime(1.5, t);
15
+ ```
16
+
17
+ **Correct (safe gain):**
18
+
19
+ ```ts
20
+ gain.gain.setValueAtTime(0.3, t);
21
+ ```
@@ -0,0 +1,23 @@
1
+ ---
2
+ title: Active State Scale Transform
3
+ impact: HIGH
4
+ impactDescription: Missing active state makes interactive elements feel unresponsive and reduces tactile feedback.
5
+ tags: physics, interaction, active-state
6
+ ---
7
+
8
+ ## Active State Scale Transform
9
+
10
+ Interactive elements must have active/pressed state with scale transform.
11
+
12
+ **Incorrect (no active state):**
13
+
14
+ ```css
15
+ .button:hover { background: var(--gray-3); }
16
+ /* Missing :active state */
17
+ ```
18
+
19
+ **Correct (active state present):**
20
+
21
+ ```css
22
+ .button:active { transform: scale(0.98); }
23
+ ```
@@ -0,0 +1,22 @@
1
+ ---
2
+ title: Stagger Under 50ms Per Item
3
+ impact: MEDIUM
4
+ impactDescription: Excessive stagger delays list readiness and feels sluggish; keep per-item delay minimal.
5
+ tags: physics, stagger, list-animation
6
+ ---
7
+
8
+ ## Stagger Under 50ms Per Item
9
+
10
+ Stagger delays must not exceed 50ms per item.
11
+
12
+ **Incorrect (excessive stagger):**
13
+
14
+ ```tsx
15
+ transition={{ staggerChildren: 0.15 }}
16
+ ```
17
+
18
+ **Correct (reasonable stagger):**
19
+
20
+ ```tsx
21
+ transition={{ staggerChildren: 0.03 }}
22
+ ```
@@ -0,0 +1,23 @@
1
+ ---
2
+ title: Springs for Overshoot and Settle
3
+ impact: HIGH
4
+ impactDescription: Easing cannot produce natural overshoot; springs are required for organic bounce-and-settle motion.
5
+ tags: physics, spring, overshoot
6
+ ---
7
+
8
+ ## Springs for Overshoot and Settle
9
+
10
+ Use springs (not easing) when overshoot-and-settle is needed.
11
+
12
+ **Incorrect (easing for bounce):**
13
+
14
+ ```tsx
15
+ <motion.div transition={{ duration: 0.3, ease: "easeOut" }} />
16
+ // When element should bounce/settle
17
+ ```
18
+
19
+ **Correct (spring physics):**
20
+
21
+ ```tsx
22
+ <motion.div transition={{ type: "spring", stiffness: 500, damping: 30 }} />
23
+ ```
@@ -0,0 +1,22 @@
1
+ ---
2
+ title: Subtle Squash and Stretch
3
+ impact: MEDIUM
4
+ impactDescription: Excessive squash/stretch feels cartoonish and distracts from the interface; subtle deformation adds polish.
5
+ tags: physics, squash-stretch, deformation
6
+ ---
7
+
8
+ ## Subtle Squash and Stretch
9
+
10
+ Squash/stretch deformation must be subtle (0.95-1.05 range).
11
+
12
+ **Incorrect (excessive deformation):**
13
+
14
+ ```tsx
15
+ <motion.div whileTap={{ scale: 0.8 }} />
16
+ ```
17
+
18
+ **Correct (subtle deformation):**
19
+
20
+ ```tsx
21
+ <motion.div whileTap={{ scale: 0.98 }} />
22
+ ```
@@ -0,0 +1,27 @@
1
+ ---
2
+ title: Use hitSlop to Trigger Predictions Earlier
3
+ impact: MEDIUM
4
+ tags: prefetch, hit-slop, target
5
+ ---
6
+
7
+ ## Use hitSlop to Trigger Predictions Earlier
8
+
9
+ Expand the invisible prediction area around elements with hitSlop to start loading sooner.
10
+
11
+ **Incorrect (tight prediction area):**
12
+
13
+ ```tsx
14
+ const { elementRef } = useForesight({
15
+ callback: () => prefetch(),
16
+ hitSlop: 0,
17
+ });
18
+ ```
19
+
20
+ **Correct (expanded prediction area):**
21
+
22
+ ```tsx
23
+ const { elementRef } = useForesight({
24
+ callback: () => prefetch(),
25
+ hitSlop: 20,
26
+ });
27
+ ```
@@ -0,0 +1,19 @@
1
+ ---
2
+ title: Prefetch on Keyboard Navigation
3
+ impact: MEDIUM
4
+ tags: prefetch, keyboard, tab, a11y
5
+ ---
6
+
7
+ ## Prefetch on Keyboard Navigation
8
+
9
+ Monitor focus changes and prefetch when the user is a few tab stops away from a registered element.
10
+
11
+ **Correct (tab-aware prefetching):**
12
+
13
+ ```tsx
14
+ const { elementRef } = useForesight({
15
+ callback: () => router.prefetch("/settings"),
16
+ name: "settings-link",
17
+ // Tab prediction fires when focus approaches
18
+ });
19
+ ```
@@ -0,0 +1,22 @@
1
+ ---
2
+ title: Prefetch by Intent, Not Viewport
3
+ impact: HIGH
4
+ tags: prefetch, viewport, intent, bundle-size
5
+ ---
6
+
7
+ ## Prefetch by Intent, Not Viewport
8
+
9
+ Don't prefetch everything visible in the viewport. Prefetch based on user intent to avoid wasted bandwidth.
10
+
11
+ **Incorrect (prefetch all visible links):**
12
+
13
+ ```tsx
14
+ <Link href="/page" prefetch={true}>Page</Link>
15
+ ```
16
+
17
+ **Correct (intent-based prefetching):**
18
+
19
+ ```tsx
20
+ <Link href="/page" prefetch={false}>Page</Link>
21
+ // Let trajectory/hover prediction handle it
22
+ ```
@@ -0,0 +1,34 @@
1
+ ---
2
+ title: Fall Back Gracefully on Touch Devices
3
+ impact: MEDIUM
4
+ tags: prefetch, touch, mobile, fallback
5
+ ---
6
+
7
+ ## Fall Back Gracefully on Touch Devices
8
+
9
+ Touch devices have no cursor. Fall back to viewport or touch-start strategies automatically.
10
+
11
+ **Incorrect (assumes cursor exists):**
12
+
13
+ ```tsx
14
+ function PrefetchLink({ href, children }) {
15
+ return (
16
+ <Link
17
+ href={href}
18
+ onMouseMove={() => prefetch(href)}
19
+ >
20
+ {children}
21
+ </Link>
22
+ );
23
+ }
24
+ ```
25
+
26
+ **Correct (device-aware strategy):**
27
+
28
+ ```tsx
29
+ const { elementRef } = useForesight({
30
+ callback: () => router.prefetch(href),
31
+ hitSlop: 20,
32
+ });
33
+ // Automatically falls back to touch-start on mobile
34
+ ```
@@ -0,0 +1,32 @@
1
+ ---
2
+ title: Trajectory Prediction Over Hover Prefetching
3
+ impact: HIGH
4
+ tags: prefetch, trajectory, hover, performance
5
+ ---
6
+
7
+ ## Trajectory Prediction Over Hover Prefetching
8
+
9
+ Hover prefetching starts too late. Trajectory prediction fires while the cursor is still in motion, reclaiming 100-200ms.
10
+
11
+ **Incorrect (waits for hover):**
12
+
13
+ ```tsx
14
+ <Link
15
+ href="/about"
16
+ onMouseEnter={() => router.prefetch("/about")}
17
+ >
18
+ About
19
+ </Link>
20
+ ```
21
+
22
+ **Correct (trajectory-based):**
23
+
24
+ ```tsx
25
+ const { elementRef } = useForesight({
26
+ callback: () => router.prefetch("/about"),
27
+ hitSlop: 20,
28
+ name: "about-link",
29
+ });
30
+
31
+ <Link ref={elementRef} href="/about">About</Link>
32
+ ```
@@ -0,0 +1,13 @@
1
+ ---
2
+ title: Use Predictive Prefetching Selectively
3
+ impact: MEDIUM
4
+ tags: prefetch, selective, performance
5
+ ---
6
+
7
+ ## Use Predictive Prefetching Selectively
8
+
9
+ Predictive prefetching doesn't belong in every project. Use it where navigation latency is noticeable.
10
+
11
+ **Good use cases:** data-heavy dashboards, multi-page apps with slow API responses, e-commerce product pages.
12
+
13
+ **Bad use cases:** static sites with instant navigation, single-page apps with all data preloaded.
@@ -0,0 +1,31 @@
1
+ ---
2
+ title: Disable Interactions on Exiting Elements
3
+ impact: MEDIUM
4
+ tags: presence, interaction, exit
5
+ ---
6
+
7
+ ## Disable Interactions on Exiting Elements
8
+
9
+ Disable interactions on exiting elements using isPresent.
10
+
11
+ **Incorrect (clickable during exit):**
12
+
13
+ ```tsx
14
+ function Card() {
15
+ const isPresent = useIsPresent();
16
+ return <button onClick={handleClick}>Click</button>;
17
+ }
18
+ ```
19
+
20
+ **Correct (disabled during exit):**
21
+
22
+ ```tsx
23
+ function Card() {
24
+ const isPresent = useIsPresent();
25
+ return (
26
+ <button onClick={handleClick} disabled={!isPresent}>
27
+ Click
28
+ </button>
29
+ );
30
+ }
31
+ ```
@@ -0,0 +1,31 @@
1
+ ---
2
+ title: useIsPresent in Child Component
3
+ impact: HIGH
4
+ tags: presence, hook, component-hierarchy
5
+ ---
6
+
7
+ ## useIsPresent in Child Component
8
+
9
+ useIsPresent must be called from child of AnimatePresence, not parent.
10
+
11
+ **Incorrect (hook in parent):**
12
+
13
+ ```tsx
14
+ function Parent() {
15
+ const isPresent = useIsPresent();
16
+ return (
17
+ <AnimatePresence>
18
+ {show && <Child />}
19
+ </AnimatePresence>
20
+ );
21
+ }
22
+ ```
23
+
24
+ **Correct (hook in child):**
25
+
26
+ ```tsx
27
+ function Child() {
28
+ const isPresent = useIsPresent();
29
+ return <motion.div data-exiting={!isPresent} />;
30
+ }
31
+ ```
@@ -0,0 +1,37 @@
1
+ ---
2
+ title: Call safeToRemove After Async Work
3
+ impact: HIGH
4
+ tags: presence, safe-to-remove, async
5
+ ---
6
+
7
+ ## Call safeToRemove After Async Work
8
+
9
+ When using usePresence, always call safeToRemove after async work.
10
+
11
+ **Incorrect (missing safeToRemove):**
12
+
13
+ ```tsx
14
+ function AsyncComponent() {
15
+ const [isPresent, safeToRemove] = usePresence();
16
+
17
+ useEffect(() => {
18
+ if (!isPresent) {
19
+ cleanup();
20
+ }
21
+ }, [isPresent]);
22
+ }
23
+ ```
24
+
25
+ **Correct (safeToRemove called):**
26
+
27
+ ```tsx
28
+ function AsyncComponent() {
29
+ const [isPresent, safeToRemove] = usePresence();
30
+
31
+ useEffect(() => {
32
+ if (!isPresent) {
33
+ cleanup().then(safeToRemove);
34
+ }
35
+ }, [isPresent, safeToRemove]);
36
+ }
37
+ ```
@@ -0,0 +1,28 @@
1
+ ---
2
+ title: Content Property Required for Pseudo-Elements
3
+ impact: HIGH
4
+ tags: pseudo, content, before-after
5
+ ---
6
+
7
+ ## Content Property Required for Pseudo-Elements
8
+
9
+ ::before and ::after require content property to render.
10
+
11
+ **Incorrect (missing content):**
12
+
13
+ ```css
14
+ .button::before {
15
+ position: absolute;
16
+ background: var(--gray-3);
17
+ }
18
+ ```
19
+
20
+ **Correct (content set):**
21
+
22
+ ```css
23
+ .button::before {
24
+ content: "";
25
+ position: absolute;
26
+ background: var(--gray-3);
27
+ }
28
+ ```
@@ -0,0 +1,27 @@
1
+ ---
2
+ title: Use ::first-line for Typographic Treatments
3
+ impact: LOW
4
+ tags: pseudo, first-line, typography
5
+ ---
6
+
7
+ ## Use ::first-line for Typographic Treatments
8
+
9
+ Use ::first-line for drop-cap-adjacent styling without JavaScript or hardcoded spans.
10
+
11
+ **Incorrect (manual span):**
12
+
13
+ ```tsx
14
+ <p>
15
+ <span className={styles["first-line"]}>The opening line of this paragraph</span>
16
+ is styled differently from the rest.
17
+ </p>
18
+ ```
19
+
20
+ **Correct (native ::first-line):**
21
+
22
+ ```css
23
+ .article p:first-of-type::first-line {
24
+ font-variant-caps: small-caps;
25
+ font-weight: var(--font-weight-medium);
26
+ }
27
+ ```
@@ -0,0 +1,31 @@
1
+ ---
2
+ title: Hit Target Expansion with Pseudo-Elements
3
+ impact: MEDIUM
4
+ tags: pseudo, hit-target, accessibility
5
+ ---
6
+
7
+ ## Hit Target Expansion with Pseudo-Elements
8
+
9
+ Use negative inset values to expand hit targets without extra markup.
10
+
11
+ **Incorrect (wrapper for hit target):**
12
+
13
+ ```tsx
14
+ <div className={styles.wrapper}>
15
+ <a className={styles.link}>Link</a>
16
+ </div>
17
+ ```
18
+
19
+ **Correct (pseudo-element expansion):**
20
+
21
+ ```css
22
+ .link {
23
+ position: relative;
24
+ }
25
+
26
+ .link::before {
27
+ content: "";
28
+ position: absolute;
29
+ inset: -8px -12px;
30
+ }
31
+ ```
@@ -0,0 +1,28 @@
1
+ ---
2
+ title: Use ::marker for Custom List Bullets
3
+ impact: LOW
4
+ tags: pseudo, marker, list, bullets
5
+ ---
6
+
7
+ ## Use ::marker for Custom List Bullets
8
+
9
+ Use ::marker to style list bullets without extra elements or background-image hacks.
10
+
11
+ **Incorrect (background image hack):**
12
+
13
+ ```css
14
+ li {
15
+ list-style: none;
16
+ background: url("bullet.svg") no-repeat 0 4px;
17
+ padding-left: 20px;
18
+ }
19
+ ```
20
+
21
+ **Correct (native ::marker):**
22
+
23
+ ```css
24
+ li::marker {
25
+ color: var(--gray-8);
26
+ font-size: 0.8em;
27
+ }
28
+ ```
@@ -0,0 +1,32 @@
1
+ ---
2
+ title: Pseudo-Elements Over DOM Nodes
3
+ impact: MEDIUM
4
+ tags: pseudo, dom, decorative
5
+ ---
6
+
7
+ ## Pseudo-Elements Over DOM Nodes
8
+
9
+ Use pseudo-elements for decorative content instead of extra DOM nodes.
10
+
11
+ **Incorrect (extra DOM node):**
12
+
13
+ ```tsx
14
+ <button className={styles.button}>
15
+ <span className={styles.background} />
16
+ Click me
17
+ </button>
18
+ ```
19
+
20
+ **Correct (pseudo-element):**
21
+
22
+ ```tsx
23
+ <button className={styles.button}>
24
+ Click me
25
+ </button>
26
+ ```
27
+ ```css
28
+ .button::before {
29
+ content: "";
30
+ /* decorative background */
31
+ }
32
+ ```
@@ -0,0 +1,33 @@
1
+ ---
2
+ title: Position Relative Parent for Pseudo-Elements
3
+ impact: HIGH
4
+ tags: pseudo, position, relative
5
+ ---
6
+
7
+ ## Position Relative Parent for Pseudo-Elements
8
+
9
+ Parent must have position: relative for absolute pseudo-elements.
10
+
11
+ **Incorrect (no position on parent):**
12
+
13
+ ```css
14
+ .button::before {
15
+ content: "";
16
+ position: absolute;
17
+ inset: 0;
18
+ }
19
+ ```
20
+
21
+ **Correct (parent positioned):**
22
+
23
+ ```css
24
+ .button {
25
+ position: relative;
26
+ }
27
+
28
+ .button::before {
29
+ content: "";
30
+ position: absolute;
31
+ inset: 0;
32
+ }
33
+ ```
@@ -0,0 +1,37 @@
1
+ ---
2
+ title: Z-Index Layering for Pseudo-Elements
3
+ impact: MEDIUM
4
+ tags: pseudo, z-index, layering
5
+ ---
6
+
7
+ ## Z-Index Layering for Pseudo-Elements
8
+
9
+ Pseudo-elements need z-index to layer correctly with content.
10
+
11
+ **Incorrect (covers text):**
12
+
13
+ ```css
14
+ .button::before {
15
+ content: "";
16
+ position: absolute;
17
+ inset: 0;
18
+ background: var(--gray-3);
19
+ }
20
+ ```
21
+
22
+ **Correct (layered behind):**
23
+
24
+ ```css
25
+ .button {
26
+ position: relative;
27
+ z-index: 1;
28
+ }
29
+
30
+ .button::before {
31
+ content: "";
32
+ position: absolute;
33
+ inset: 0;
34
+ background: var(--gray-3);
35
+ z-index: -1;
36
+ }
37
+ ```