@rune-kit/rune 2.8.0 → 2.11.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 (287) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +68 -34
  3. package/agents/adversary.md +27 -0
  4. package/agents/architect.md +19 -29
  5. package/agents/asset-creator.md +18 -4
  6. package/agents/audit.md +25 -4
  7. package/agents/autopsy.md +19 -4
  8. package/agents/ba.md +35 -0
  9. package/agents/brainstorm.md +31 -4
  10. package/agents/browser-pilot.md +21 -4
  11. package/agents/coder.md +21 -29
  12. package/agents/completion-gate.md +20 -4
  13. package/agents/constraint-check.md +18 -4
  14. package/agents/context-engine.md +22 -4
  15. package/agents/context-pack.md +32 -0
  16. package/agents/cook.md +41 -4
  17. package/agents/db.md +19 -4
  18. package/agents/debug.md +33 -4
  19. package/agents/dependency-doctor.md +20 -4
  20. package/agents/deploy.md +27 -4
  21. package/agents/design.md +22 -4
  22. package/agents/doc-processor.md +27 -0
  23. package/agents/docs-seeker.md +19 -4
  24. package/agents/docs.md +31 -0
  25. package/agents/fix.md +37 -4
  26. package/agents/git.md +29 -0
  27. package/agents/hallucination-guard.md +20 -4
  28. package/agents/incident.md +21 -4
  29. package/agents/integrity-check.md +18 -4
  30. package/agents/journal.md +19 -4
  31. package/agents/launch.md +32 -4
  32. package/agents/logic-guardian.md +26 -11
  33. package/agents/marketing.md +23 -4
  34. package/agents/mcp-builder.md +26 -0
  35. package/agents/neural-memory.md +30 -0
  36. package/agents/onboard.md +22 -4
  37. package/agents/perf.md +21 -4
  38. package/agents/plan.md +29 -4
  39. package/agents/preflight.md +22 -4
  40. package/agents/problem-solver.md +20 -4
  41. package/agents/rescue.md +23 -4
  42. package/agents/research.md +19 -4
  43. package/agents/researcher.md +19 -29
  44. package/agents/retro.md +32 -0
  45. package/agents/review-intake.md +20 -4
  46. package/agents/review.md +32 -4
  47. package/agents/reviewer.md +20 -28
  48. package/agents/safeguard.md +19 -4
  49. package/agents/sast.md +18 -4
  50. package/agents/scaffold.md +41 -0
  51. package/agents/scanner.md +19 -28
  52. package/agents/scope-guard.md +18 -4
  53. package/agents/scout.md +23 -4
  54. package/agents/sentinel-env.md +26 -0
  55. package/agents/sentinel.md +33 -4
  56. package/agents/sequential-thinking.md +20 -4
  57. package/agents/session-bridge.md +24 -4
  58. package/agents/skill-forge.md +22 -4
  59. package/agents/skill-router.md +26 -4
  60. package/agents/slides.md +24 -0
  61. package/agents/surgeon.md +19 -4
  62. package/agents/team.md +30 -4
  63. package/agents/test.md +36 -4
  64. package/agents/trend-scout.md +17 -4
  65. package/agents/verification.md +20 -4
  66. package/agents/video-creator.md +20 -4
  67. package/agents/watchdog.md +19 -4
  68. package/agents/worktree.md +17 -4
  69. package/commands/rune.md +168 -168
  70. package/compiler/__tests__/analytics.test.js +370 -0
  71. package/compiler/adapters/openclaw.js +2 -2
  72. package/compiler/analytics.js +385 -0
  73. package/compiler/bin/rune.js +68 -2
  74. package/compiler/dashboard.js +883 -0
  75. package/compiler/transforms/branding.js +1 -1
  76. package/contexts/dev.md +34 -34
  77. package/contexts/research.md +43 -43
  78. package/contexts/review.md +55 -55
  79. package/extensions/ai-ml/PACK.md +88 -88
  80. package/extensions/ai-ml/skills/ai-agents.md +172 -172
  81. package/extensions/ai-ml/skills/code-sandbox.md +187 -187
  82. package/extensions/ai-ml/skills/deep-research.md +146 -146
  83. package/extensions/ai-ml/skills/embedding-search.md +66 -66
  84. package/extensions/ai-ml/skills/fine-tuning-guide.md +74 -74
  85. package/extensions/ai-ml/skills/llm-architect.md +125 -125
  86. package/extensions/ai-ml/skills/llm-integration.md +64 -64
  87. package/extensions/ai-ml/skills/prompt-patterns.md +72 -72
  88. package/extensions/ai-ml/skills/rag-patterns.md +66 -66
  89. package/extensions/ai-ml/skills/web-extraction.md +114 -114
  90. package/extensions/analytics/PACK.md +92 -92
  91. package/extensions/analytics/skills/ab-testing.md +72 -72
  92. package/extensions/analytics/skills/dashboard-patterns.md +83 -83
  93. package/extensions/analytics/skills/data-validation.md +68 -68
  94. package/extensions/analytics/skills/funnel-analysis.md +81 -81
  95. package/extensions/analytics/skills/sql-patterns.md +57 -57
  96. package/extensions/analytics/skills/statistical-analysis.md +79 -79
  97. package/extensions/analytics/skills/tracking-setup.md +71 -71
  98. package/extensions/backend/PACK.md +104 -104
  99. package/extensions/backend/skills/api-patterns.md +84 -84
  100. package/extensions/backend/skills/async-pipeline.md +193 -193
  101. package/extensions/backend/skills/auth-patterns.md +97 -97
  102. package/extensions/backend/skills/background-jobs.md +133 -133
  103. package/extensions/backend/skills/caching-patterns.md +108 -108
  104. package/extensions/backend/skills/cli-generation.md +133 -133
  105. package/extensions/backend/skills/database-patterns.md +87 -87
  106. package/extensions/backend/skills/middleware-patterns.md +104 -104
  107. package/extensions/chrome-ext/PACK.md +93 -93
  108. package/extensions/chrome-ext/skills/cws-preflight.md +143 -143
  109. package/extensions/chrome-ext/skills/cws-publish.md +104 -104
  110. package/extensions/chrome-ext/skills/ext-ai-integration.md +251 -251
  111. package/extensions/chrome-ext/skills/ext-messaging.md +139 -139
  112. package/extensions/chrome-ext/skills/ext-storage.md +133 -133
  113. package/extensions/chrome-ext/skills/mv3-scaffold.md +164 -164
  114. package/extensions/content/PACK.md +96 -96
  115. package/extensions/content/skills/blog-patterns.md +88 -88
  116. package/extensions/content/skills/cms-integration.md +131 -131
  117. package/extensions/content/skills/content-scoring.md +107 -107
  118. package/extensions/content/skills/i18n.md +83 -83
  119. package/extensions/content/skills/mdx-authoring.md +137 -137
  120. package/extensions/content/skills/reference.md +1014 -1014
  121. package/extensions/content/skills/seo-patterns.md +67 -67
  122. package/extensions/content/skills/video-repurpose.md +153 -153
  123. package/extensions/devops/PACK.md +101 -101
  124. package/extensions/devops/skills/chaos-testing.md +67 -67
  125. package/extensions/devops/skills/ci-cd.md +75 -75
  126. package/extensions/devops/skills/docker.md +58 -58
  127. package/extensions/devops/skills/edge-serverless.md +163 -163
  128. package/extensions/devops/skills/infra-as-code.md +158 -158
  129. package/extensions/devops/skills/kubernetes.md +110 -110
  130. package/extensions/devops/skills/monitoring.md +57 -57
  131. package/extensions/devops/skills/server-setup.md +64 -64
  132. package/extensions/devops/skills/ssl-domain.md +42 -42
  133. package/extensions/ecommerce/PACK.md +116 -116
  134. package/extensions/ecommerce/skills/cart-system.md +79 -79
  135. package/extensions/ecommerce/skills/inventory-mgmt.md +102 -102
  136. package/extensions/ecommerce/skills/order-management.md +126 -126
  137. package/extensions/ecommerce/skills/payment-integration.md +472 -472
  138. package/extensions/ecommerce/skills/shopify-dev.md +69 -69
  139. package/extensions/ecommerce/skills/subscription-billing.md +93 -93
  140. package/extensions/ecommerce/skills/tax-compliance.md +117 -117
  141. package/extensions/gamedev/PACK.md +142 -142
  142. package/extensions/gamedev/skills/asset-pipeline.md +74 -74
  143. package/extensions/gamedev/skills/audio-system.md +129 -129
  144. package/extensions/gamedev/skills/camera-system.md +87 -87
  145. package/extensions/gamedev/skills/ecs.md +98 -98
  146. package/extensions/gamedev/skills/game-loops.md +72 -72
  147. package/extensions/gamedev/skills/input-system.md +199 -199
  148. package/extensions/gamedev/skills/multiplayer.md +180 -180
  149. package/extensions/gamedev/skills/particles.md +105 -105
  150. package/extensions/gamedev/skills/physics-engine.md +89 -89
  151. package/extensions/gamedev/skills/scene-management.md +146 -146
  152. package/extensions/gamedev/skills/threejs-patterns.md +90 -90
  153. package/extensions/gamedev/skills/webgl.md +71 -71
  154. package/extensions/mobile/PACK.md +106 -106
  155. package/extensions/mobile/skills/app-store-connect.md +152 -152
  156. package/extensions/mobile/skills/app-store-prep.md +66 -66
  157. package/extensions/mobile/skills/deep-linking.md +109 -109
  158. package/extensions/mobile/skills/flutter.md +60 -60
  159. package/extensions/mobile/skills/ios-build-pipeline.md +142 -142
  160. package/extensions/mobile/skills/native-bridge.md +66 -66
  161. package/extensions/mobile/skills/ota-updates.md +97 -97
  162. package/extensions/mobile/skills/push-notifications.md +111 -111
  163. package/extensions/mobile/skills/react-native.md +82 -82
  164. package/extensions/saas/PACK.md +116 -116
  165. package/extensions/saas/skills/billing-integration.md +200 -200
  166. package/extensions/saas/skills/feature-flags.md +130 -130
  167. package/extensions/saas/skills/multi-tenant.md +103 -103
  168. package/extensions/saas/skills/onboarding-flow.md +139 -139
  169. package/extensions/saas/skills/subscription-flow.md +95 -95
  170. package/extensions/saas/skills/team-management.md +144 -144
  171. package/extensions/security/PACK.md +99 -99
  172. package/extensions/security/skills/api-security.md +140 -140
  173. package/extensions/security/skills/compliance.md +68 -68
  174. package/extensions/security/skills/owasp-audit.md +64 -64
  175. package/extensions/security/skills/pentest-patterns.md +77 -77
  176. package/extensions/security/skills/secret-mgmt.md +65 -65
  177. package/extensions/security/skills/supply-chain.md +65 -65
  178. package/extensions/trading/PACK.md +80 -80
  179. package/extensions/trading/skills/chart-components.md +55 -55
  180. package/extensions/trading/skills/experiment-loop.md +125 -125
  181. package/extensions/trading/skills/fintech-patterns.md +47 -47
  182. package/extensions/trading/skills/indicator-library.md +58 -58
  183. package/extensions/trading/skills/quant-analysis.md +111 -111
  184. package/extensions/trading/skills/realtime-data.md +58 -58
  185. package/extensions/trading/skills/trade-logic.md +104 -104
  186. package/extensions/ui/PACK.md +130 -130
  187. package/extensions/ui/skills/a11y-audit.md +91 -91
  188. package/extensions/ui/skills/animation-patterns.md +127 -106
  189. package/extensions/ui/skills/component-patterns.md +100 -75
  190. package/extensions/ui/skills/design-decision.md +108 -108
  191. package/extensions/ui/skills/design-system.md +68 -68
  192. package/extensions/ui/skills/landing-patterns.md +155 -155
  193. package/extensions/ui/skills/palette-picker.md +173 -173
  194. package/extensions/ui/skills/react-health.md +90 -90
  195. package/extensions/ui/skills/type-system.md +125 -125
  196. package/extensions/ui/skills/web-vitals.md +153 -153
  197. package/extensions/zalo/PACK.md +145 -145
  198. package/extensions/zalo/skills/zalo-oa-mcp.md +317 -317
  199. package/extensions/zalo/skills/zalo-oa-messaging.md +429 -429
  200. package/extensions/zalo/skills/zalo-oa-setup.md +236 -236
  201. package/extensions/zalo/skills/zalo-oa-webhook.md +189 -189
  202. package/extensions/zalo/skills/zalo-personal-messaging.md +194 -194
  203. package/extensions/zalo/skills/zalo-personal-setup.md +153 -153
  204. package/extensions/zalo/skills/zalo-rate-guard.md +219 -219
  205. package/hooks/auto-format/index.cjs +48 -48
  206. package/hooks/context-watch/index.cjs +95 -68
  207. package/hooks/hooks.json +111 -111
  208. package/hooks/metrics-collector/index.cjs +86 -42
  209. package/hooks/post-session-reflect/index.cjs +189 -153
  210. package/hooks/pre-compact/index.cjs +95 -95
  211. package/hooks/run-hook.cmd +1 -1
  212. package/hooks/secrets-scan/index.cjs +100 -100
  213. package/hooks/session-start/index.cjs +71 -65
  214. package/hooks/typecheck/index.cjs +65 -65
  215. package/package.json +63 -63
  216. package/references/ui-pro-max-data/LICENSE-UI-PRO-MAX +21 -21
  217. package/references/ui-pro-max-data/charts.csv +26 -26
  218. package/references/ui-pro-max-data/colors.csv +161 -161
  219. package/references/ui-pro-max-data/styles.csv +68 -68
  220. package/references/ui-pro-max-data/typography.csv +74 -74
  221. package/references/ui-pro-max-data/ui-reasoning.csv +162 -162
  222. package/references/ui-pro-max-data/ux-guidelines.csv +99 -99
  223. package/skills/adversary/SKILL.md +283 -283
  224. package/skills/asset-creator/SKILL.md +157 -157
  225. package/skills/audit/SKILL.md +148 -2
  226. package/skills/autopsy/SKILL.md +335 -259
  227. package/skills/autopsy/references/repo-analysis-patterns.md +113 -0
  228. package/skills/ba/SKILL.md +72 -2
  229. package/skills/brainstorm/SKILL.md +342 -341
  230. package/skills/browser-pilot/SKILL.md +168 -168
  231. package/skills/constraint-check/SKILL.md +165 -165
  232. package/skills/context-engine/SKILL.md +404 -404
  233. package/skills/cook/SKILL.md +917 -834
  234. package/skills/cook/references/output-format.md +33 -0
  235. package/skills/db/SKILL.md +273 -272
  236. package/skills/debug/SKILL.md +465 -443
  237. package/skills/dependency-doctor/SKILL.md +265 -235
  238. package/skills/deploy/SKILL.md +274 -231
  239. package/skills/design/DESIGN-REFERENCE.md +365 -365
  240. package/skills/design/SKILL.md +589 -482
  241. package/skills/doc-processor/SKILL.md +254 -254
  242. package/skills/docs/SKILL.md +374 -373
  243. package/skills/docs-seeker/SKILL.md +177 -177
  244. package/skills/fix/SKILL.md +330 -308
  245. package/skills/git/SKILL.md +339 -339
  246. package/skills/graft/SKILL.md +352 -0
  247. package/skills/graft/references/challenge-framework.md +98 -0
  248. package/skills/graft/references/mode-decision.md +44 -0
  249. package/skills/hallucination-guard/SKILL.md +219 -219
  250. package/skills/incident/SKILL.md +254 -251
  251. package/skills/integrity-check/SKILL.md +169 -169
  252. package/skills/journal/SKILL.md +240 -238
  253. package/skills/launch/SKILL.md +344 -342
  254. package/skills/logic-guardian/SKILL.md +251 -251
  255. package/skills/marketing/SKILL.md +290 -245
  256. package/skills/mcp-builder/SKILL.md +425 -423
  257. package/skills/mcp-builder/references/auto-discovery-pattern.md +169 -0
  258. package/skills/neural-memory/SKILL.md +362 -362
  259. package/skills/onboard/SKILL.md +404 -403
  260. package/skills/perf/SKILL.md +346 -346
  261. package/skills/plan/SKILL.md +433 -370
  262. package/skills/plan/references/feature-map.md +84 -0
  263. package/skills/preflight/SKILL.md +415 -396
  264. package/skills/problem-solver/SKILL.md +380 -284
  265. package/skills/rescue/SKILL.md +474 -450
  266. package/skills/retro/SKILL.md +5 -1
  267. package/skills/review/SKILL.md +612 -535
  268. package/skills/review-intake/SKILL.md +249 -249
  269. package/skills/safeguard/SKILL.md +200 -200
  270. package/skills/sast/SKILL.md +190 -190
  271. package/skills/scaffold/SKILL.md +328 -286
  272. package/skills/scope-guard/SKILL.md +180 -162
  273. package/skills/scout/SKILL.md +263 -263
  274. package/skills/sentinel/SKILL.md +382 -353
  275. package/skills/sentinel-env/SKILL.md +254 -254
  276. package/skills/sequential-thinking/SKILL.md +234 -234
  277. package/skills/session-bridge/SKILL.md +543 -397
  278. package/skills/skill-forge/SKILL.md +581 -539
  279. package/skills/skill-router/{skill.md → SKILL.md} +30 -2
  280. package/skills/surgeon/SKILL.md +215 -215
  281. package/skills/team/SKILL.md +556 -514
  282. package/skills/test/SKILL.md +614 -587
  283. package/skills/trend-scout/SKILL.md +145 -145
  284. package/skills/verification/SKILL.md +326 -325
  285. package/skills/video-creator/SKILL.md +201 -201
  286. package/skills/watchdog/SKILL.md +168 -168
  287. package/skills/worktree/SKILL.md +140 -140
@@ -1,88 +1,88 @@
1
- ---
2
- name: "blog-patterns"
3
- pack: "@rune/content"
4
- description: "Post management, categories/tags, pagination, RSS feeds, reading time, related posts, comment systems."
5
- model: sonnet
6
- tools: [Read, Edit, Write, Grep, Glob, Bash]
7
- ---
8
-
9
- # blog-patterns
10
-
11
- Blog system patterns — post management, categories/tags, pagination, RSS feeds, reading time, related posts, comment systems.
12
-
13
- #### Workflow
14
-
15
- **Step 1 — Detect blog architecture**
16
- Use Glob to find blog-related files: `blog/`, `posts/`, `articles/`, `*.mdx`, `*.md` in content directories. Use Grep to find blog utilities: `getStaticPaths`, `generateStaticParams`, `allPosts`, `contentlayer`, `reading-time`. Read the post listing page and individual post page to understand: data source, routing strategy, and rendering pipeline.
17
-
18
- **Step 2 — Audit blog completeness**
19
- Check for: missing RSS feed (`feed.xml` or `/api/rss`), no reading time estimation, pagination absent on listing pages (all posts loaded at once), no category/tag filtering, missing related posts, no draft/published state, and OG images not generated per-post.
20
-
21
- **Step 3 — Emit blog patterns**
22
- Emit: typed post schema with frontmatter validation, paginated listing with category filter, RSS feed generator, reading time calculator, and related posts by tag similarity.
23
-
24
- #### Example
25
-
26
- ```typescript
27
- // Next.js App Router — blog listing with pagination and categories
28
- import { allPosts, type Post } from 'contentlayer/generated';
29
-
30
- function getPublishedPosts(category?: string): Post[] {
31
- return allPosts
32
- .filter(p => p.status === 'published')
33
- .filter(p => !category || p.category === category)
34
- .sort((a, b) => new Date(b.date).getTime() - new Date(a.date).getTime());
35
- }
36
-
37
- // Reading time utility
38
- function readingTime(content: string): string {
39
- const words = content.trim().split(/\s+/).length;
40
- const minutes = Math.ceil(words / 238);
41
- return `${minutes} min read`;
42
- }
43
-
44
- // RSS feed — app/feed.xml/route.ts
45
- export async function GET() {
46
- const posts = getPublishedPosts();
47
- const xml = `<?xml version="1.0" encoding="UTF-8"?>
48
- <rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
49
- <channel>
50
- <title>My Blog</title>
51
- <link>${process.env.SITE_URL}</link>
52
- <atom:link href="${process.env.SITE_URL}/feed.xml" rel="self" type="application/rss+xml"/>
53
- ${posts.slice(0, 20).map(p => `<item>
54
- <title>${escapeXml(p.title)}</title>
55
- <link>${process.env.SITE_URL}${p.url}</link>
56
- <pubDate>${new Date(p.date).toUTCString()}</pubDate>
57
- <description>${escapeXml(p.excerpt)}</description>
58
- </item>`).join('\n')}
59
- </channel>
60
- </rss>`;
61
- return new Response(xml, { headers: { 'Content-Type': 'application/xml' } });
62
- }
63
-
64
- // Related posts by tag overlap — score by number of shared tags
65
- function getRelatedPosts(current: Post, all: Post[], limit = 3): Post[] {
66
- const currentTags = new Set(current.tags ?? []);
67
- return all
68
- .filter(p => p.slug !== current.slug && p.status === 'published')
69
- .map(p => ({ post: p, score: (p.tags ?? []).filter(t => currentTags.has(t)).length }))
70
- .filter(({ score }) => score > 0)
71
- .sort((a, b) => b.score - a.score)
72
- .slice(0, limit)
73
- .map(({ post }) => post);
74
- }
75
-
76
- // Paginated listing
77
- const PAGE_SIZE = 10;
78
- function paginatePosts(posts: Post[], page: number) {
79
- const start = (page - 1) * PAGE_SIZE;
80
- return {
81
- posts: posts.slice(start, start + PAGE_SIZE),
82
- total: posts.length,
83
- totalPages: Math.ceil(posts.length / PAGE_SIZE),
84
- hasNext: start + PAGE_SIZE < posts.length,
85
- hasPrev: page > 1,
86
- };
87
- }
88
- ```
1
+ ---
2
+ name: "blog-patterns"
3
+ pack: "@rune/content"
4
+ description: "Post management, categories/tags, pagination, RSS feeds, reading time, related posts, comment systems."
5
+ model: sonnet
6
+ tools: [Read, Edit, Write, Grep, Glob, Bash]
7
+ ---
8
+
9
+ # blog-patterns
10
+
11
+ Blog system patterns — post management, categories/tags, pagination, RSS feeds, reading time, related posts, comment systems.
12
+
13
+ #### Workflow
14
+
15
+ **Step 1 — Detect blog architecture**
16
+ Use Glob to find blog-related files: `blog/`, `posts/`, `articles/`, `*.mdx`, `*.md` in content directories. Use Grep to find blog utilities: `getStaticPaths`, `generateStaticParams`, `allPosts`, `contentlayer`, `reading-time`. Read the post listing page and individual post page to understand: data source, routing strategy, and rendering pipeline.
17
+
18
+ **Step 2 — Audit blog completeness**
19
+ Check for: missing RSS feed (`feed.xml` or `/api/rss`), no reading time estimation, pagination absent on listing pages (all posts loaded at once), no category/tag filtering, missing related posts, no draft/published state, and OG images not generated per-post.
20
+
21
+ **Step 3 — Emit blog patterns**
22
+ Emit: typed post schema with frontmatter validation, paginated listing with category filter, RSS feed generator, reading time calculator, and related posts by tag similarity.
23
+
24
+ #### Example
25
+
26
+ ```typescript
27
+ // Next.js App Router — blog listing with pagination and categories
28
+ import { allPosts, type Post } from 'contentlayer/generated';
29
+
30
+ function getPublishedPosts(category?: string): Post[] {
31
+ return allPosts
32
+ .filter(p => p.status === 'published')
33
+ .filter(p => !category || p.category === category)
34
+ .sort((a, b) => new Date(b.date).getTime() - new Date(a.date).getTime());
35
+ }
36
+
37
+ // Reading time utility
38
+ function readingTime(content: string): string {
39
+ const words = content.trim().split(/\s+/).length;
40
+ const minutes = Math.ceil(words / 238);
41
+ return `${minutes} min read`;
42
+ }
43
+
44
+ // RSS feed — app/feed.xml/route.ts
45
+ export async function GET() {
46
+ const posts = getPublishedPosts();
47
+ const xml = `<?xml version="1.0" encoding="UTF-8"?>
48
+ <rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
49
+ <channel>
50
+ <title>My Blog</title>
51
+ <link>${process.env.SITE_URL}</link>
52
+ <atom:link href="${process.env.SITE_URL}/feed.xml" rel="self" type="application/rss+xml"/>
53
+ ${posts.slice(0, 20).map(p => `<item>
54
+ <title>${escapeXml(p.title)}</title>
55
+ <link>${process.env.SITE_URL}${p.url}</link>
56
+ <pubDate>${new Date(p.date).toUTCString()}</pubDate>
57
+ <description>${escapeXml(p.excerpt)}</description>
58
+ </item>`).join('\n')}
59
+ </channel>
60
+ </rss>`;
61
+ return new Response(xml, { headers: { 'Content-Type': 'application/xml' } });
62
+ }
63
+
64
+ // Related posts by tag overlap — score by number of shared tags
65
+ function getRelatedPosts(current: Post, all: Post[], limit = 3): Post[] {
66
+ const currentTags = new Set(current.tags ?? []);
67
+ return all
68
+ .filter(p => p.slug !== current.slug && p.status === 'published')
69
+ .map(p => ({ post: p, score: (p.tags ?? []).filter(t => currentTags.has(t)).length }))
70
+ .filter(({ score }) => score > 0)
71
+ .sort((a, b) => b.score - a.score)
72
+ .slice(0, limit)
73
+ .map(({ post }) => post);
74
+ }
75
+
76
+ // Paginated listing
77
+ const PAGE_SIZE = 10;
78
+ function paginatePosts(posts: Post[], page: number) {
79
+ const start = (page - 1) * PAGE_SIZE;
80
+ return {
81
+ posts: posts.slice(start, start + PAGE_SIZE),
82
+ total: posts.length,
83
+ totalPages: Math.ceil(posts.length / PAGE_SIZE),
84
+ hasNext: start + PAGE_SIZE < posts.length,
85
+ hasPrev: page > 1,
86
+ };
87
+ }
88
+ ```
@@ -1,131 +1,131 @@
1
- ---
2
- name: "cms-integration"
3
- pack: "@rune/content"
4
- description: "Sanity, Contentful, Strapi, PocketBase. Content modeling, preview mode, webhook-triggered rebuilds, draft/published workflows."
5
- model: sonnet
6
- tools: [Read, Edit, Write, Grep, Glob, Bash]
7
- ---
8
-
9
- # cms-integration
10
-
11
- CMS integration — Sanity, Contentful, Strapi, PocketBase. Content modeling, preview mode, webhook-triggered rebuilds, draft/published workflows.
12
-
13
- #### Workflow
14
-
15
- **Step 1 — Detect CMS setup**
16
- Use Grep to find CMS SDK usage: `createClient` (Sanity), `contentful`, `strapi`, `PocketBase`, `GROQ`, `graphql` in content-fetching files. Read the CMS client initialization and content queries to understand: CMS provider, content types, preview mode setup, and caching strategy.
17
-
18
- **Step 2 — Audit CMS integration**
19
- Check for: no preview/draft mode (editors can't preview before publish), missing webhook for on-demand ISR (content updates require full rebuild), no content validation (malformed CMS data crashes the page), stale cache without revalidation strategy, images served from CMS without optimization (no next/image or equivalent), and missing error boundary for CMS fetch failures.
20
-
21
- **Step 3 — Emit CMS patterns**
22
- For Sanity: emit typed GROQ queries with Zod validation, preview mode toggle, and webhook handler. For Contentful: emit typed GraphQL queries, draft/published content switching. For any CMS: emit ISR revalidation endpoint and image optimization pipeline.
23
-
24
- #### Example — Sanity
25
-
26
- ```typescript
27
- // Sanity — typed client with preview mode and ISR webhook
28
- import { createClient, type QueryParams } from '@sanity/client';
29
- import { z } from 'zod';
30
-
31
- const client = createClient({
32
- projectId: process.env.SANITY_PROJECT_ID!,
33
- dataset: 'production',
34
- apiVersion: '2024-01-01',
35
- useCdn: true,
36
- });
37
-
38
- const previewClient = client.withConfig({ useCdn: false, token: process.env.SANITY_PREVIEW_TOKEN });
39
-
40
- const PostSchema = z.object({
41
- _id: z.string(),
42
- title: z.string(),
43
- slug: z.string(),
44
- body: z.array(z.any()),
45
- publishedAt: z.string().datetime(),
46
- author: z.object({ name: z.string(), image: z.string().url().optional() }),
47
- });
48
-
49
- export async function getPost(slug: string, preview = false) {
50
- const query = `*[_type == "post" && slug.current == $slug][0]{
51
- _id, title, "slug": slug.current, body, publishedAt,
52
- "author": author->{ name, "image": image.asset->url }
53
- }`;
54
- const result = await (preview ? previewClient : client).fetch(query, { slug });
55
- return PostSchema.parse(result);
56
- }
57
-
58
- // Webhook handler for on-demand ISR — app/api/revalidate/route.ts
59
- export async function POST(req: Request) {
60
- const body = await req.json();
61
- const secret = req.headers.get('x-sanity-webhook-secret');
62
- if (secret !== process.env.SANITY_WEBHOOK_SECRET) {
63
- return new Response('Unauthorized', { status: 401 });
64
- }
65
- const { revalidatePath } = await import('next/cache');
66
- revalidatePath(`/blog/${body.slug.current}`);
67
- return Response.json({ revalidated: true });
68
- }
69
- ```
70
-
71
- #### Example — Contentful
72
-
73
- ```typescript
74
- // Contentful — typed GraphQL with draft/published switching
75
- import { createClient } from 'contentful';
76
-
77
- const client = createClient({
78
- space: process.env.CONTENTFUL_SPACE_ID!,
79
- accessToken: process.env.CONTENTFUL_ACCESS_TOKEN!,
80
- });
81
-
82
- const previewClient = createClient({
83
- space: process.env.CONTENTFUL_SPACE_ID!,
84
- accessToken: process.env.CONTENTFUL_PREVIEW_TOKEN!,
85
- host: 'preview.contentful.com',
86
- });
87
-
88
- export async function getArticle(slug: string, preview = false) {
89
- const c = preview ? previewClient : client;
90
- const entries = await c.getEntries({
91
- content_type: 'article',
92
- 'fields.slug': slug,
93
- include: 2,
94
- limit: 1,
95
- });
96
- if (!entries.items.length) return null;
97
- const entry = entries.items[0];
98
- return {
99
- title: entry.fields.title as string,
100
- slug: entry.fields.slug as string,
101
- body: entry.fields.body,
102
- publishedAt: entry.sys.createdAt,
103
- };
104
- }
105
- ```
106
-
107
- #### Example — Strapi
108
-
109
- ```typescript
110
- // Strapi v5 — REST with populate and draft/live modes
111
- const STRAPI = process.env.STRAPI_URL ?? 'http://localhost:1337';
112
- const TOKEN = process.env.STRAPI_API_TOKEN!;
113
-
114
- async function strapiGet<T>(path: string, params: Record<string, string> = {}): Promise<T> {
115
- const url = new URL(`${STRAPI}/api${path}`);
116
- Object.entries(params).forEach(([k, v]) => url.searchParams.set(k, v));
117
- const res = await fetch(url.toString(), {
118
- headers: { Authorization: `Bearer ${TOKEN}` },
119
- next: { revalidate: 60 },
120
- });
121
- if (!res.ok) throw new Error(`Strapi error: ${res.status}`);
122
- return res.json();
123
- }
124
-
125
- export const getArticles = () =>
126
- strapiGet<{ data: StrapiArticle[] }>('/articles', {
127
- 'filters[publishedAt][$notNull]': 'true',
128
- 'populate': 'cover,author,category',
129
- 'sort': 'publishedAt:desc',
130
- });
131
- ```
1
+ ---
2
+ name: "cms-integration"
3
+ pack: "@rune/content"
4
+ description: "Sanity, Contentful, Strapi, PocketBase. Content modeling, preview mode, webhook-triggered rebuilds, draft/published workflows."
5
+ model: sonnet
6
+ tools: [Read, Edit, Write, Grep, Glob, Bash]
7
+ ---
8
+
9
+ # cms-integration
10
+
11
+ CMS integration — Sanity, Contentful, Strapi, PocketBase. Content modeling, preview mode, webhook-triggered rebuilds, draft/published workflows.
12
+
13
+ #### Workflow
14
+
15
+ **Step 1 — Detect CMS setup**
16
+ Use Grep to find CMS SDK usage: `createClient` (Sanity), `contentful`, `strapi`, `PocketBase`, `GROQ`, `graphql` in content-fetching files. Read the CMS client initialization and content queries to understand: CMS provider, content types, preview mode setup, and caching strategy.
17
+
18
+ **Step 2 — Audit CMS integration**
19
+ Check for: no preview/draft mode (editors can't preview before publish), missing webhook for on-demand ISR (content updates require full rebuild), no content validation (malformed CMS data crashes the page), stale cache without revalidation strategy, images served from CMS without optimization (no next/image or equivalent), and missing error boundary for CMS fetch failures.
20
+
21
+ **Step 3 — Emit CMS patterns**
22
+ For Sanity: emit typed GROQ queries with Zod validation, preview mode toggle, and webhook handler. For Contentful: emit typed GraphQL queries, draft/published content switching. For any CMS: emit ISR revalidation endpoint and image optimization pipeline.
23
+
24
+ #### Example — Sanity
25
+
26
+ ```typescript
27
+ // Sanity — typed client with preview mode and ISR webhook
28
+ import { createClient, type QueryParams } from '@sanity/client';
29
+ import { z } from 'zod';
30
+
31
+ const client = createClient({
32
+ projectId: process.env.SANITY_PROJECT_ID!,
33
+ dataset: 'production',
34
+ apiVersion: '2024-01-01',
35
+ useCdn: true,
36
+ });
37
+
38
+ const previewClient = client.withConfig({ useCdn: false, token: process.env.SANITY_PREVIEW_TOKEN });
39
+
40
+ const PostSchema = z.object({
41
+ _id: z.string(),
42
+ title: z.string(),
43
+ slug: z.string(),
44
+ body: z.array(z.any()),
45
+ publishedAt: z.string().datetime(),
46
+ author: z.object({ name: z.string(), image: z.string().url().optional() }),
47
+ });
48
+
49
+ export async function getPost(slug: string, preview = false) {
50
+ const query = `*[_type == "post" && slug.current == $slug][0]{
51
+ _id, title, "slug": slug.current, body, publishedAt,
52
+ "author": author->{ name, "image": image.asset->url }
53
+ }`;
54
+ const result = await (preview ? previewClient : client).fetch(query, { slug });
55
+ return PostSchema.parse(result);
56
+ }
57
+
58
+ // Webhook handler for on-demand ISR — app/api/revalidate/route.ts
59
+ export async function POST(req: Request) {
60
+ const body = await req.json();
61
+ const secret = req.headers.get('x-sanity-webhook-secret');
62
+ if (secret !== process.env.SANITY_WEBHOOK_SECRET) {
63
+ return new Response('Unauthorized', { status: 401 });
64
+ }
65
+ const { revalidatePath } = await import('next/cache');
66
+ revalidatePath(`/blog/${body.slug.current}`);
67
+ return Response.json({ revalidated: true });
68
+ }
69
+ ```
70
+
71
+ #### Example — Contentful
72
+
73
+ ```typescript
74
+ // Contentful — typed GraphQL with draft/published switching
75
+ import { createClient } from 'contentful';
76
+
77
+ const client = createClient({
78
+ space: process.env.CONTENTFUL_SPACE_ID!,
79
+ accessToken: process.env.CONTENTFUL_ACCESS_TOKEN!,
80
+ });
81
+
82
+ const previewClient = createClient({
83
+ space: process.env.CONTENTFUL_SPACE_ID!,
84
+ accessToken: process.env.CONTENTFUL_PREVIEW_TOKEN!,
85
+ host: 'preview.contentful.com',
86
+ });
87
+
88
+ export async function getArticle(slug: string, preview = false) {
89
+ const c = preview ? previewClient : client;
90
+ const entries = await c.getEntries({
91
+ content_type: 'article',
92
+ 'fields.slug': slug,
93
+ include: 2,
94
+ limit: 1,
95
+ });
96
+ if (!entries.items.length) return null;
97
+ const entry = entries.items[0];
98
+ return {
99
+ title: entry.fields.title as string,
100
+ slug: entry.fields.slug as string,
101
+ body: entry.fields.body,
102
+ publishedAt: entry.sys.createdAt,
103
+ };
104
+ }
105
+ ```
106
+
107
+ #### Example — Strapi
108
+
109
+ ```typescript
110
+ // Strapi v5 — REST with populate and draft/live modes
111
+ const STRAPI = process.env.STRAPI_URL ?? 'http://localhost:1337';
112
+ const TOKEN = process.env.STRAPI_API_TOKEN!;
113
+
114
+ async function strapiGet<T>(path: string, params: Record<string, string> = {}): Promise<T> {
115
+ const url = new URL(`${STRAPI}/api${path}`);
116
+ Object.entries(params).forEach(([k, v]) => url.searchParams.set(k, v));
117
+ const res = await fetch(url.toString(), {
118
+ headers: { Authorization: `Bearer ${TOKEN}` },
119
+ next: { revalidate: 60 },
120
+ });
121
+ if (!res.ok) throw new Error(`Strapi error: ${res.status}`);
122
+ return res.json();
123
+ }
124
+
125
+ export const getArticles = () =>
126
+ strapiGet<{ data: StrapiArticle[] }>('/articles', {
127
+ 'filters[publishedAt][$notNull]': 'true',
128
+ 'populate': 'cover,author,category',
129
+ 'sort': 'publishedAt:desc',
130
+ });
131
+ ```
@@ -1,107 +1,107 @@
1
- ---
2
- name: "content-scoring"
3
- pack: "@rune/content"
4
- description: "Engagement and virality scoring for content pieces. Analyze hooks, readability, shareability, and platform fit."
5
- model: sonnet
6
- tools: [Read, Edit, Write, Grep, Glob, Bash]
7
- ---
8
-
9
- # content-scoring
10
-
11
- Engagement and virality scoring for content pieces. Analyze hooks, readability, shareability, and platform fit. Works for both video clips and written articles.
12
-
13
- #### Workflow
14
-
15
- **Step 1 — Detect content type**
16
- Determine if scoring target is:
17
- - **Video clip** (from video-repurpose pipeline or standalone)
18
- - **Blog post / article** (markdown, MDX, or CMS content)
19
- - **Social post** (short-form text, tweet, thread)
20
-
21
- **Step 2 — Score across 4 dimensions**
22
- ```typescript
23
- interface ContentScore {
24
- hook: {
25
- score: number; // 0-25
26
- type: 'question' | 'statistic' | 'story' | 'contrast' | 'bold-claim' | 'how-to';
27
- assessment: string; // Why this hook works or doesn't
28
- };
29
- engagement: {
30
- score: number; // 0-25
31
- readability: number; // Flesch-Kincaid grade level
32
- pacing: string; // 'too-slow' | 'good' | 'too-fast'
33
- callToAction: boolean;
34
- };
35
- value: {
36
- score: number; // 0-25
37
- teaches: boolean;
38
- entertains: boolean;
39
- uniqueInsight: boolean;
40
- };
41
- shareability: {
42
- score: number; // 0-25
43
- emotionalTrigger: string | null; // 'surprise' | 'anger' | 'joy' | 'fear'
44
- quotable: string[]; // Extract quotable one-liners
45
- platformFit: Record<Platform, number>; // 0-10 per platform
46
- };
47
- total: number; // 0-100
48
- tier: 'viral' | 'strong' | 'average' | 'weak'; // >80 viral, >60 strong, >40 average
49
- }
50
- ```
51
-
52
- **Step 3 — Platform-specific optimization hints**
53
- Each platform has different engagement patterns:
54
- | Platform | Hook Window | Optimal Length | Key Factor |
55
- |----------|-------------|---------------|------------|
56
- | TikTok | 0-1s | 15-30s | Pattern interrupt, trend audio |
57
- | YouTube | 0-3s | 8-12 min (long), 30-60s (Shorts) | Curiosity gap, retention graph |
58
- | Twitter/X | First line | 280 chars or 4-tweet thread | Hot take, data point |
59
- | LinkedIn | First 2 lines | 150-300 words | Professional insight, personal story |
60
- | Blog | Title + first paragraph | 1500-2500 words | SEO keyword + value promise |
61
-
62
- **Step 4 — Emit improvement suggestions**
63
- For each dimension scoring < 20/25, emit specific actionable improvement:
64
- - Hook weak → suggest rewrite with stronger opening pattern
65
- - Engagement low → identify pacing issues, suggest cuts or restructures
66
- - Value low → identify where content is generic, suggest unique angle
67
- - Shareability low → suggest quotable reformulations, emotional triggers
68
-
69
- #### Example
70
-
71
- ```typescript
72
- // Scoring a blog post
73
- const score = await scoreContent({
74
- type: 'article',
75
- title: 'How We Cut Our AWS Bill by 60%',
76
- content: articleMarkdown,
77
- targetPlatforms: ['blog', 'twitter', 'linkedin'],
78
- });
79
-
80
- // Result:
81
- // {
82
- // hook: { score: 22, type: 'statistic', assessment: 'Strong — specific number creates curiosity' },
83
- // engagement: { score: 18, readability: 8.2, pacing: 'good', callToAction: true },
84
- // value: { score: 20, teaches: true, entertains: false, uniqueInsight: true },
85
- // shareability: {
86
- // score: 19, emotionalTrigger: 'surprise',
87
- // quotable: ['We were paying $12K/mo for a service we used 3% of'],
88
- // platformFit: { blog: 9, twitter: 8, linkedin: 9 }
89
- // },
90
- // total: 79, tier: 'strong'
91
- // }
92
-
93
- // Improvement suggestions:
94
- // - Shareability: Add a contrarian angle ("Everyone says X, but we found Y")
95
- // - Engagement: Add a visual comparison (before/after cost graph)
96
- ```
97
-
98
- ```typescript
99
- // Scoring a video clip
100
- const clipScore = await scoreContent({
101
- type: 'video-clip',
102
- transcript: clipTranscript,
103
- duration: 28_000, // 28 seconds
104
- hookType: 'question',
105
- targetPlatforms: ['tiktok', 'youtube-shorts', 'instagram-reels'],
106
- });
107
- ```
1
+ ---
2
+ name: "content-scoring"
3
+ pack: "@rune/content"
4
+ description: "Engagement and virality scoring for content pieces. Analyze hooks, readability, shareability, and platform fit."
5
+ model: sonnet
6
+ tools: [Read, Edit, Write, Grep, Glob, Bash]
7
+ ---
8
+
9
+ # content-scoring
10
+
11
+ Engagement and virality scoring for content pieces. Analyze hooks, readability, shareability, and platform fit. Works for both video clips and written articles.
12
+
13
+ #### Workflow
14
+
15
+ **Step 1 — Detect content type**
16
+ Determine if scoring target is:
17
+ - **Video clip** (from video-repurpose pipeline or standalone)
18
+ - **Blog post / article** (markdown, MDX, or CMS content)
19
+ - **Social post** (short-form text, tweet, thread)
20
+
21
+ **Step 2 — Score across 4 dimensions**
22
+ ```typescript
23
+ interface ContentScore {
24
+ hook: {
25
+ score: number; // 0-25
26
+ type: 'question' | 'statistic' | 'story' | 'contrast' | 'bold-claim' | 'how-to';
27
+ assessment: string; // Why this hook works or doesn't
28
+ };
29
+ engagement: {
30
+ score: number; // 0-25
31
+ readability: number; // Flesch-Kincaid grade level
32
+ pacing: string; // 'too-slow' | 'good' | 'too-fast'
33
+ callToAction: boolean;
34
+ };
35
+ value: {
36
+ score: number; // 0-25
37
+ teaches: boolean;
38
+ entertains: boolean;
39
+ uniqueInsight: boolean;
40
+ };
41
+ shareability: {
42
+ score: number; // 0-25
43
+ emotionalTrigger: string | null; // 'surprise' | 'anger' | 'joy' | 'fear'
44
+ quotable: string[]; // Extract quotable one-liners
45
+ platformFit: Record<Platform, number>; // 0-10 per platform
46
+ };
47
+ total: number; // 0-100
48
+ tier: 'viral' | 'strong' | 'average' | 'weak'; // >80 viral, >60 strong, >40 average
49
+ }
50
+ ```
51
+
52
+ **Step 3 — Platform-specific optimization hints**
53
+ Each platform has different engagement patterns:
54
+ | Platform | Hook Window | Optimal Length | Key Factor |
55
+ |----------|-------------|---------------|------------|
56
+ | TikTok | 0-1s | 15-30s | Pattern interrupt, trend audio |
57
+ | YouTube | 0-3s | 8-12 min (long), 30-60s (Shorts) | Curiosity gap, retention graph |
58
+ | Twitter/X | First line | 280 chars or 4-tweet thread | Hot take, data point |
59
+ | LinkedIn | First 2 lines | 150-300 words | Professional insight, personal story |
60
+ | Blog | Title + first paragraph | 1500-2500 words | SEO keyword + value promise |
61
+
62
+ **Step 4 — Emit improvement suggestions**
63
+ For each dimension scoring < 20/25, emit specific actionable improvement:
64
+ - Hook weak → suggest rewrite with stronger opening pattern
65
+ - Engagement low → identify pacing issues, suggest cuts or restructures
66
+ - Value low → identify where content is generic, suggest unique angle
67
+ - Shareability low → suggest quotable reformulations, emotional triggers
68
+
69
+ #### Example
70
+
71
+ ```typescript
72
+ // Scoring a blog post
73
+ const score = await scoreContent({
74
+ type: 'article',
75
+ title: 'How We Cut Our AWS Bill by 60%',
76
+ content: articleMarkdown,
77
+ targetPlatforms: ['blog', 'twitter', 'linkedin'],
78
+ });
79
+
80
+ // Result:
81
+ // {
82
+ // hook: { score: 22, type: 'statistic', assessment: 'Strong — specific number creates curiosity' },
83
+ // engagement: { score: 18, readability: 8.2, pacing: 'good', callToAction: true },
84
+ // value: { score: 20, teaches: true, entertains: false, uniqueInsight: true },
85
+ // shareability: {
86
+ // score: 19, emotionalTrigger: 'surprise',
87
+ // quotable: ['We were paying $12K/mo for a service we used 3% of'],
88
+ // platformFit: { blog: 9, twitter: 8, linkedin: 9 }
89
+ // },
90
+ // total: 79, tier: 'strong'
91
+ // }
92
+
93
+ // Improvement suggestions:
94
+ // - Shareability: Add a contrarian angle ("Everyone says X, but we found Y")
95
+ // - Engagement: Add a visual comparison (before/after cost graph)
96
+ ```
97
+
98
+ ```typescript
99
+ // Scoring a video clip
100
+ const clipScore = await scoreContent({
101
+ type: 'video-clip',
102
+ transcript: clipTranscript,
103
+ duration: 28_000, // 28 seconds
104
+ hookType: 'question',
105
+ targetPlatforms: ['tiktok', 'youtube-shorts', 'instagram-reels'],
106
+ });
107
+ ```