opencode-skills-collection 3.0.31 → 3.0.33

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 (51) hide show
  1. package/bundled-skills/.antigravity-install-manifest.json +14 -1
  2. package/bundled-skills/bilig-workpaper/SKILL.md +12 -3
  3. package/bundled-skills/bumblebee/SKILL.md +6 -2
  4. package/bundled-skills/bun-development/SKILL.md +5 -3
  5. package/bundled-skills/cloud-penetration-testing/SKILL.md +5 -3
  6. package/bundled-skills/container-security-hardening/SKILL.md +1001 -0
  7. package/bundled-skills/container-security-hardening/references/base-image-comparison.md +245 -0
  8. package/bundled-skills/container-security-hardening/references/kubernetes-pod-security.md +567 -0
  9. package/bundled-skills/container-security-hardening/references/seccomp-profile-template.json +337 -0
  10. package/bundled-skills/doc2math/SKILL.md +102 -0
  11. package/bundled-skills/docs/integrations/jetski-cortex.md +3 -3
  12. package/bundled-skills/docs/integrations/jetski-gemini-loader/README.md +1 -1
  13. package/bundled-skills/docs/maintainers/repo-growth-seo.md +3 -3
  14. package/bundled-skills/docs/maintainers/skills-update-guide.md +1 -1
  15. package/bundled-skills/docs/users/bundles.md +1 -1
  16. package/bundled-skills/docs/users/claude-code-skills.md +1 -1
  17. package/bundled-skills/docs/users/gemini-cli-skills.md +1 -1
  18. package/bundled-skills/docs/users/getting-started.md +6 -2
  19. package/bundled-skills/docs/users/kiro-integration.md +1 -1
  20. package/bundled-skills/docs/users/usage.md +4 -4
  21. package/bundled-skills/docs/users/visual-guide.md +4 -4
  22. package/bundled-skills/environment-setup-guide/SKILL.md +10 -6
  23. package/bundled-skills/evolution/SKILL.md +5 -3
  24. package/bundled-skills/github-actions-advanced/SKILL.md +1100 -0
  25. package/bundled-skills/gitops-workflow/SKILL.md +5 -3
  26. package/bundled-skills/ii-commons/SKILL.md +15 -1
  27. package/bundled-skills/lemmaly/SKILL.md +15 -6
  28. package/bundled-skills/linkerd-patterns/SKILL.md +5 -3
  29. package/bundled-skills/longbridge/SKILL.md +95 -0
  30. package/bundled-skills/mercury-mcp/SKILL.md +9 -1
  31. package/bundled-skills/moatmri/SKILL.md +84 -0
  32. package/bundled-skills/nextjs-seo-indexing/SKILL.md +263 -0
  33. package/bundled-skills/openclaw-github-repo-commander/scripts/repo-audit.sh +42 -0
  34. package/bundled-skills/photopea-embedded-editor/SKILL.md +7 -3
  35. package/bundled-skills/runaway-guard/SKILL.md +331 -0
  36. package/bundled-skills/schema-markup-generator/SKILL.md +319 -0
  37. package/bundled-skills/sendblue/sendblue-api/SKILL.md +6 -1
  38. package/bundled-skills/sendblue/sendblue-cli/SKILL.md +6 -1
  39. package/bundled-skills/sendblue/sendblue-notify/SKILL.md +6 -1
  40. package/bundled-skills/sendblue/textme/SKILL.md +4 -0
  41. package/bundled-skills/social-metadata-hardening/SKILL.md +230 -0
  42. package/bundled-skills/socialclaw/SKILL.md +6 -1
  43. package/bundled-skills/uv-package-manager/resources/implementation-playbook.md +5 -3
  44. package/bundled-skills/varlock/SKILL.md +10 -6
  45. package/bundled-skills/vibe-code-cleanup/SKILL.md +231 -0
  46. package/bundled-skills/vibecode-production-qa-validator/SKILL.md +237 -0
  47. package/bundled-skills/wordpress-centric-high-seo-optimized-blogwriting-skill/SKILL.md +229 -162
  48. package/bundled-skills/yield-intelligence/SKILL.md +121 -0
  49. package/bundled-skills/youtube-full/SKILL.md +144 -0
  50. package/package.json +1 -1
  51. package/skills_index.json +330 -28
@@ -141,9 +141,11 @@ spec:
141
141
  brew install fluxcd/tap/flux
142
142
 
143
143
  # Alternative: download the official installer, inspect it, then execute it
144
- curl -fsSLo /tmp/flux-install.sh https://fluxcd.io/install.sh
145
- sed -n '1,160p' /tmp/flux-install.sh
146
- sudo bash /tmp/flux-install.sh
144
+ tmpdir="$(mktemp -d)"
145
+ trap 'rm -rf "$tmpdir"' EXIT
146
+ curl -fsSLo "$tmpdir/flux-install.sh" https://fluxcd.io/install.sh
147
+ sed -n '1,160p' "$tmpdir/flux-install.sh"
148
+ sudo bash "$tmpdir/flux-install.sh"
147
149
 
148
150
  # Bootstrap Flux
149
151
  flux bootstrap github \
@@ -43,7 +43,10 @@ Report the relevant cutoff date before interpreting recent results.
43
43
 
44
44
  ### Step 2: Search the Right Corpus
45
45
 
46
- Use exactly this command shape:
46
+ Use this argv shape. Literal examples can be typed as shown, but when the query
47
+ comes from a user prompt, pass it as an argument array through the runner API
48
+ instead of interpolating it into a shell string. Double quotes do not protect
49
+ against command substitution in generated shell commands.
47
50
 
48
51
  ```bash
49
52
  npx @intelligentinternet/ii-commons search arxiv "large language model inference" --max-results 10
@@ -51,6 +54,17 @@ npx @intelligentinternet/ii-commons search pubmed "type 2 diabetes review" --sta
51
54
  npx @intelligentinternet/ii-commons search policy "state overtime rule for agricultural workers" --jurisdictions US-CA --max-results 10
52
55
  ```
53
56
 
57
+ ```js
58
+ spawnSync("npx", [
59
+ "@intelligentinternet/ii-commons",
60
+ "search",
61
+ "arxiv",
62
+ userQuery,
63
+ "--max-results",
64
+ "10",
65
+ ]);
66
+ ```
67
+
54
68
  Choose `arxiv` for preprints and technical research, `pubmed` for biomedical and clinical literature, and `policy` for supported US policy corpora.
55
69
 
56
70
  ### Step 3: Retrieve Metadata or Markdown
@@ -141,16 +141,25 @@ The first version is the default an AI ships when asked "filter the active users
141
141
 
142
142
  The upstream repo ships a deterministic CLI scanner with the same anti-patterns this skill enforces (**59 rules across 11 languages**: JavaScript/TypeScript, Python, SQL, Java, C#, C++, Go, Rust, PHP, Ruby, Shell/Bash). Each rule has a documented why, an incorrect example, a correct example, and the sibling skill to escalate to.
143
143
 
144
- To run the scanner locally:
144
+ The scanner is optional. Do not automatically clone and run the upstream
145
+ repository from its default branch, because that executes whatever code is
146
+ current in a third-party repository. If the user explicitly wants the scanner,
147
+ pin the source to a reviewed release tag or commit, use a throwaway directory,
148
+ and show the resolved commit before running it:
145
149
 
146
150
  ```bash
147
- # Clone the upstream repo for the CLI tool
148
- git clone https://github.com/morsechimwai/lemmaly.git
149
- cd lemmaly
150
- node cli/lemmaly.js scan <path> # flag instances of anti-patterns
151
- node cli/lemmaly.js rules # list all 59 rules
151
+ # Replace <reviewed-tag-or-commit> after reviewing the upstream release.
152
+ tmpdir="$(mktemp -d)"
153
+ git clone --filter=blob:none https://github.com/morsechimwai/lemmaly.git "$tmpdir/lemmaly"
154
+ git -C "$tmpdir/lemmaly" checkout --detach <reviewed-tag-or-commit>
155
+ git -C "$tmpdir/lemmaly" rev-parse HEAD
156
+ node "$tmpdir/lemmaly/cli/lemmaly.js" scan <path>
157
+ node "$tmpdir/lemmaly/cli/lemmaly.js" rules
152
158
  ```
153
159
 
160
+ When the scan is done, remove the throwaway directory only after verifying that
161
+ `$tmpdir` points to the directory created by `mktemp -d`.
162
+
154
163
  **CRITICAL severity (error in CI):**
155
164
 
156
165
  - `js-await-in-for-loop` — N+1 over network
@@ -73,9 +73,11 @@ Production patterns for Linkerd service mesh - the lightweight, security-first s
73
73
  brew install linkerd
74
74
 
75
75
  # Alternative: download the official installer, inspect it, then execute it
76
- curl --proto '=https' --tlsv1.2 -sSfL https://run.linkerd.io/install -o /tmp/linkerd-install.sh
77
- sed -n '1,160p' /tmp/linkerd-install.sh
78
- sh /tmp/linkerd-install.sh
76
+ tmpdir="$(mktemp -d)"
77
+ trap 'rm -rf "$tmpdir"' EXIT
78
+ curl --proto '=https' --tlsv1.2 -sSfL https://run.linkerd.io/install -o "$tmpdir/linkerd-install.sh"
79
+ sed -n '1,160p' "$tmpdir/linkerd-install.sh"
80
+ sh "$tmpdir/linkerd-install.sh"
79
81
 
80
82
  # Validate cluster
81
83
  linkerd check --pre
@@ -0,0 +1,95 @@
1
+ ---
2
+ name: longbridge
3
+ description: "125+ agent skills for Longbridge Securities — real-time quotes, charts, fundamentals, portfolio analysis, options, and more for HK/US/A-share/SG markets. Trilingual: Simplified Chinese, Traditional Chinese, English."
4
+ category: finance
5
+ risk: critical
6
+ source: official
7
+ source_repo: longbridge/skills
8
+ source_type: official
9
+ date_added: "2026-05-29"
10
+ author: longbridge
11
+ tags: [finance, stocks, trading, portfolio, market-data]
12
+ tools: [claude, cursor, gemini, codex]
13
+ license: "MIT"
14
+ license_source: "https://github.com/longbridge/skills/blob/main/LICENSE"
15
+ plugin:
16
+ targets:
17
+ codex: blocked
18
+ claude: blocked
19
+ ---
20
+
21
+ # Longbridge
22
+
23
+ ## Overview
24
+
25
+ Longbridge is the official skill collection for Longbridge Securities, covering 125+ agent skills across real-time market data, chart analysis, company fundamentals, portfolio management, options, sector screening, and more. Supports HK, US, A-share (SH/SZ), and SG markets. All skills are trilingual (Simplified Chinese / Traditional Chinese / English).
26
+
27
+ Source repository: [github.com/longbridge/skills](https://github.com/longbridge/skills) (~840 stars, MIT)
28
+
29
+ ## When to Use This Skill
30
+
31
+ - Use when the user asks about stock prices, charts, or market data for HK/US/A-share/SG markets
32
+ - Use when the user wants company fundamentals, earnings, or analyst ratings
33
+ - Use when the user asks about their portfolio, positions, or account P&L via Longbridge
34
+ - Use when the user wants options analysis, sector rankings, capital flow, or news
35
+ - Use when the user asks in Chinese (Simplified or Traditional) or English about any securities topic
36
+
37
+ ## How It Works
38
+
39
+ ### Step 1: Discover the Right Subcommand
40
+
41
+ ```bash
42
+ longbridge --help
43
+ ```
44
+
45
+ List all available subcommands. Never hard-code subcommand names — the CLI evolves.
46
+
47
+ ### Step 2: Check Subcommand Options
48
+
49
+ ```bash
50
+ longbridge <subcommand> --help
51
+ ```
52
+
53
+ Confirm flags and output format before calling.
54
+
55
+ ### Step 3: Call with JSON Output
56
+
57
+ ```bash
58
+ longbridge <subcommand> --format json
59
+ ```
60
+
61
+ Parse the structured output and render in the user's language (detect from input).
62
+
63
+ ## Authentication
64
+
65
+ ```bash
66
+ longbridge auth login # Basic market data (read-only)
67
+ longbridge auth login --trade # Portfolio and account features
68
+ ```
69
+
70
+ ## Install
71
+
72
+ ```bash
73
+ # Claude Code plugin marketplace
74
+ /plugin marketplace add longbridge/skills
75
+
76
+ # Or via npx
77
+ npx skills add https://github.com/longbridge/skills
78
+ ```
79
+
80
+ ## MCP Fallback
81
+
82
+ If the `longbridge` CLI binary is not installed, fall back to MCP tools. Inspect available MCP tools at runtime — do not hard-code MCP tool names as they change with server versions.
83
+
84
+ ## Limitations
85
+
86
+ - Portfolio and account features require login with Trade scope.
87
+ - Real-time data is subject to Longbridge data subscription (delayed data available without subscription).
88
+ - Crypto symbols use `.HAS` suffix on the Longbridge platform.
89
+ - This skill does not place orders — read-only by default unless using the account write scope.
90
+
91
+ ## Security & Safety Notes
92
+
93
+ - All market data queries are read-only (no side effects).
94
+ - Watchlist mutations and order-related features follow a preview + confirm two-step protocol.
95
+ - Credentials are handled by the Longbridge auth system; this skill does not store or transmit tokens.
@@ -1,9 +1,13 @@
1
1
  ---
2
2
  name: mercury-mcp
3
3
  description: "Cheatsheet for the Mercury (proton) MCP tools. Use when connected to the Mercury MCP server to look up which mercury_* tool to call for messaging teammates, threads, tasks, automations, or admin team-graph edits."
4
- risk: safe
4
+ risk: critical
5
5
  source: community
6
6
  date_added: "2026-05-19"
7
+ plugin:
8
+ targets:
9
+ codex: blocked
10
+ claude: blocked
7
11
  ---
8
12
 
9
13
  # Mercury MCP tool cheatsheet
@@ -21,6 +25,10 @@ This skill is a lookup reference for those tools. It does not change how the
21
25
  agent works — it tells the agent which tool does what, so it picks the right
22
26
  one without guessing.
23
27
 
28
+ Because many Mercury tools mutate an external workspace, do not call send,
29
+ create, update, delete, close, status, automation, or admin tools until the user
30
+ has reviewed the exact target and payload and explicitly confirmed the action.
31
+
24
32
  ## When to Use This Skill
25
33
 
26
34
  - Use when your agent is connected to the Mercury MCP server and you need to
@@ -0,0 +1,84 @@
1
+ ---
2
+ name: moatmri
3
+ description: Analyze AI disruption pressure across a business, map competitive exposure, and produce a 90-day defensive action plan.
4
+ risk: safe
5
+ source: community
6
+ date_added: "2026-05-31"
7
+ ---
8
+
9
+ # MoatMRI — AI Disruption Pressure Analysis
10
+
11
+ *Where does intelligence pressure break this system first?*
12
+
13
+ ## When to Use This Skill
14
+
15
+ - "Is my business at risk from AI? Where am I most exposed?"
16
+ - "How would an AI-native startup take over my market?"
17
+ - "What should I do in the next 90 days to defend against AI disruption?"
18
+ - "I'm doing due diligence on [company] — what's their AI displacement risk?"
19
+ - "Where does my competitive moat actually hold against AI pressure?"
20
+
21
+ ## How It Works
22
+
23
+ ### Step 1 — Gather Inputs
24
+
25
+ Ask if not provided:
26
+ - **Industry** (e.g., "real estate", "community banking", "retail pharmacy", "law firm")
27
+ - **Entity type** (e.g., "independent broker", "solo practitioner", "regional franchise")
28
+ - **Target name** (optional — specific organization for named analysis)
29
+
30
+ ## Limitations
31
+
32
+ - Produces strategic risk analysis, not audited market research or investment advice.
33
+ - Depends on current company, market, regulatory, and competitive context supplied by the user or gathered from reliable sources.
34
+ - Treats disruption scenarios as planning tools; scores should be revisited as new evidence appears.
35
+
36
+ ### Step 2 — 10-Vector Pressure Map
37
+
38
+ Score AI disruption pressure across exactly these 10 vectors (0–10):
39
+
40
+ | # | Vector | What to Measure |
41
+ |---|--------|----------------|
42
+ | 1 | **labor_substitution** | Which roles/functions are directly automatable |
43
+ | 2 | **customer_interface** | How AI changes how customers reach this entity |
44
+ | 3 | **knowledge_commoditization** | Does AI commoditize the expertise this entity sells |
45
+ | 4 | **pricing_pressure** | Does AI enable lower-cost competitors to undercut |
46
+ | 5 | **supply_chain_automation** | Does AI change input costs or supplier relationships |
47
+ | 6 | **data_moat** | Does this entity have proprietary data AI can't replicate |
48
+ | 7 | **trust_relationship_moat** | How much does customer loyalty protect against displacement |
49
+ | 8 | **distribution_channel_disruption** | Does AI create new channels that bypass this entity |
50
+ | 9 | **regulatory_compliance_exposure** | Does AI alter the regulatory or liability landscape |
51
+ | 10 | **decision_speed_gap** | Does AI accelerate decisions in ways that disadvantage this entity |
52
+
53
+ For each vector produce: **score**, **headline**, **near_term** (12 months), **far_term** (3 years).
54
+
55
+ **Aggregate risk score:** mean of all 10 vectors. Flag any vector ≥ 7 as critical.
56
+
57
+ ### Step 3 — AI Front-Door Takeover Storyboard
58
+
59
+ 6-step narrative of how an AI-native competitor displaces this entity:
60
+ 1. The entry point
61
+ 2. The wedge (first 10% of market)
62
+ 3. The acceleration (what makes it compound)
63
+ 4. The tipping point (when incumbent can't recover)
64
+ 5. The aftermath
65
+ 6. The survivor profile
66
+
67
+ ### Step 4 — 90-Day Counterstrike Plan
68
+
69
+ - **Track A (Days 0–30):** Immediate defense — what to stop, what to protect
70
+ - **Track B (Days 31–60):** Intelligence-layer build — data/relationships to fortify
71
+ - **Track C (Days 61–90):** Offensive positioning — use AI pressure as competitive weapon
72
+
73
+ ## Best Practices
74
+
75
+ - ✅ Score all 10 vectors before calculating aggregate — resist stopping at obvious ones
76
+ - ✅ Keep the storyboard specific to industry/entity, not generic disruption narrative
77
+ - ✅ Track C should be actionable within 90 days, not aspirational 3-year strategy
78
+ - ❌ Don't conflate data_moat with trust_relationship_moat — they protect differently
79
+
80
+ ## Additional Resources
81
+
82
+ - Repository: [thebrierfox/moatmri-skill](https://github.com/thebrierfox/moatmri-skill)
83
+ - Full BYOK tool: [ace-license-server-production.up.railway.app/byok/moatmri](https://ace-license-server-production.up.railway.app/byok/moatmri)
84
+ - Built by [IntuiTek¹](https://intuitek.ai) (~K¹) — MIT License
@@ -0,0 +1,263 @@
1
+ ---
2
+ name: nextjs-seo-indexing
3
+ description: "Fix SEO indexing issues, crawl budget problems, and Search Console coverage errors for Next.js apps. Covers canonical tags, noindex audits, sitemap health, static rendering, and internal linking."
4
+ category: seo
5
+ risk: safe
6
+ source: self
7
+ source_type: self
8
+ date_added: "2026-05-31"
9
+ author: Whoisabhishekadhikari
10
+ tags: [seo, indexing, nextjs, search-console, crawl-budget, canonical, sitemap]
11
+ tools: [claude, cursor, gemini, claude-code]
12
+ version: 1.0.0
13
+ ---
14
+
15
+ # Next.js SEO Indexing & Crawl Budget Skill
16
+
17
+ Fix Google Search Console coverage issues, canonical problems, sitemap errors, and crawl budget waste in Next.js apps.
18
+
19
+ ---
20
+
21
+ ## When to Use
22
+
23
+ - Use when a Next.js site has Google Search Console coverage issues such as duplicate canonicals, accidental noindex, crawl waste, or discovered-but-not-indexed URLs.
24
+ - Use when auditing sitemap, robots.txt, redirect, internal-linking, or static-rendering problems before an SEO release.
25
+ - Use when you need framework-specific examples for Next.js App Router metadata, `generateMetadata`, `robots.js`, and sitemap routes.
26
+
27
+ ---
28
+
29
+ ## Understanding Search Console Coverage States
30
+
31
+ | Status | Meaning | Fix |
32
+ |--------|---------|-----|
33
+ | Crawled – not indexed | Google crawled but chose not to index | Improve content quality + canonical + internal links |
34
+ | Duplicate without canonical | Multiple URLs serve same content, no canonical | Add explicit canonical to the preferred URL |
35
+ | Excluded by noindex | `noindex` tag present | Remove noindex if page should be indexed |
36
+ | Duplicate, Google chose different canonical | Google prefers a different URL than you specified | Align canonical with the URL Google naturally picks |
37
+ | Alternative page with proper canonical | Correct — non-preferred duplicate pointing to canonical | Expected behavior, not a problem |
38
+ | Not found 404 | Page deleted or URL changed | Add redirect or restore page |
39
+ | Discovered – not indexed | Google knows it exists but hasn't crawled it | Improve internal linking + crawl budget |
40
+ | Page with redirect | Redirect chain or redirect to wrong target | Shorten redirect chain, verify destination |
41
+
42
+ ---
43
+
44
+ ## Step 1 — Canonical Audit
45
+
46
+ ### Next.js App Router (metadata export)
47
+ ```js
48
+ // app/blog/my-post/page.js
49
+ export const metadata = {
50
+ title: 'My Post Title',
51
+ alternates: {
52
+ canonical: 'https://www.yourdomain.com/blog/my-post',
53
+ },
54
+ };
55
+ ```
56
+
57
+ ### Next.js App Router (generateMetadata)
58
+ ```js
59
+ export async function generateMetadata({ params }) {
60
+ return {
61
+ alternates: {
62
+ canonical: `https://www.yourdomain.com/blog/${params.slug}`,
63
+ },
64
+ };
65
+ }
66
+ ```
67
+
68
+ ### Common canonical mistakes to fix:
69
+ ```js
70
+ // ❌ WRONG — relative URL
71
+ canonical: '/blog/my-post'
72
+
73
+ // ❌ WRONG — missing trailing slash inconsistency
74
+ // (pick one and stick with it sitewide)
75
+
76
+ // ✓ CORRECT — absolute URL, consistent scheme + subdomain
77
+ canonical: 'https://www.yourdomain.com/blog/my-post'
78
+ ```
79
+
80
+ ---
81
+
82
+ ## Step 2 — Noindex Audit
83
+
84
+ Find pages that are accidentally noindexed:
85
+
86
+ ```bash
87
+ # Search for noindex in metadata
88
+ grep -r "noindex\|robots.*noindex" --include="*.{js,ts,jsx,tsx}" app/ pages/ -l
89
+
90
+ # Check layout.js — a noindex here affects ALL pages
91
+ grep -n "robots" app/layout.js
92
+ ```
93
+
94
+ In Next.js App Router, `robots` in the root layout applies globally. Only set it there if you want the whole site affected.
95
+
96
+ ```js
97
+ // app/layout.js — only set robots if you need sitewide control
98
+ export const metadata = {
99
+ // ✓ Allow indexing
100
+ robots: { index: true, follow: true },
101
+ // ❌ This would noindex the entire site:
102
+ // robots: { index: false }
103
+ };
104
+ ```
105
+
106
+ ---
107
+
108
+ ## Step 3 — Sitemap Health
109
+
110
+ ### Verify sitemap routes return 200 + valid XML
111
+ ```bash
112
+ curl -sI https://www.yourdomain.com/sitemap.xml | grep -i "content-type\|status"
113
+ curl -s https://www.yourdomain.com/sitemap.xml | head -20
114
+ ```
115
+
116
+ ### Next.js App Router sitemap (recommended pattern)
117
+ ```js
118
+ // app/sitemap.js
119
+ export default async function sitemap() {
120
+ const baseUrl = 'https://www.yourdomain.com';
121
+
122
+ // Static pages
123
+ const staticPages = [
124
+ { url: baseUrl, lastModified: new Date(), changeFrequency: 'daily', priority: 1.0 },
125
+ { url: `${baseUrl}/about`, lastModified: new Date(), changeFrequency: 'monthly', priority: 0.8 },
126
+ ];
127
+
128
+ // Dynamic pages (fetch from DB or CMS)
129
+ const posts = await getPosts(); // your data fetch
130
+ const dynamicPages = posts.map(post => ({
131
+ url: `${baseUrl}/blog/${post.slug}`,
132
+ lastModified: new Date(post.updatedAt),
133
+ changeFrequency: 'weekly',
134
+ priority: 0.7,
135
+ }));
136
+
137
+ return [...staticPages, ...dynamicPages];
138
+ }
139
+ ```
140
+
141
+ ### Multiple sitemaps (sitemap index)
142
+ ```js
143
+ // app/sitemap-tools/sitemap.js
144
+ // app/sitemap-blog/sitemap.js
145
+ // Each returns an array of URL entries
146
+ ```
147
+
148
+ ---
149
+
150
+ ## Step 4 — Static Rendering Verification
151
+
152
+ Pages must be statically generated (or SSR with metadata in HTML) for Google to see SEO tags.
153
+
154
+ ```bash
155
+ # Check build output — pages should show ● (static) not λ (dynamic)
156
+ npm run build 2>&1 | grep -E "○|●|λ|/blog|/tools"
157
+ ```
158
+
159
+ ```
160
+ ○ /about (static)
161
+ ● /blog/[slug] (SSG) ← good
162
+ λ /api/data (serverless) ← expected for APIs
163
+ ```
164
+
165
+ If important pages are `λ` (fully dynamic with no static generation), add:
166
+
167
+ ```js
168
+ // app/blog/[slug]/page.js
169
+ export async function generateStaticParams() {
170
+ const posts = await getPosts();
171
+ return posts.map(post => ({ slug: post.slug }));
172
+ }
173
+ ```
174
+
175
+ ---
176
+
177
+ ## Step 5 — Internal Linking Audit
178
+
179
+ Pages with zero internal links are rarely indexed. Every important page should be reachable from:
180
+ 1. Homepage or navigation
181
+ 2. A sitemap
182
+ 3. At least one other content page
183
+
184
+ ```bash
185
+ # Find pages that have no inbound links from other pages
186
+ # (manual check — grep for the slug across all files)
187
+ grep -r "/blog/my-orphan-post" --include="*.{js,ts,jsx,tsx,md}" . | grep -v "sitemap\|the-page-itself"
188
+ ```
189
+
190
+ ---
191
+
192
+ ## Step 6 — Redirect Audit
193
+
194
+ ```bash
195
+ # Find all redirects in Next.js config
196
+ grep -A 3 "redirects" next.config.js
197
+
198
+ # Check for redirect chains (A → B → C — should be A → C)
199
+ # Test a suspected chain:
200
+ curl -sI https://www.yourdomain.com/old-url | grep -i location
201
+ ```
202
+
203
+ ```js
204
+ // next.config.js — keep redirects flat (no chains)
205
+ async redirects() {
206
+ return [
207
+ {
208
+ source: '/old-url',
209
+ destination: '/new-url', // Must NOT itself redirect
210
+ permanent: true, // 308 for SEO
211
+ },
212
+ ];
213
+ }
214
+ ```
215
+
216
+ ---
217
+
218
+ ## Step 7 — robots.txt Check
219
+
220
+ ```bash
221
+ curl -s https://www.yourdomain.com/robots.txt
222
+ ```
223
+
224
+ ```
225
+ # ✓ Good
226
+ User-agent: *
227
+ Allow: /
228
+ Sitemap: https://www.yourdomain.com/sitemap.xml
229
+
230
+ # ❌ Bad — disallows crawling of important content
231
+ Disallow: /blog/
232
+ Disallow: /tools/
233
+ ```
234
+
235
+ ```js
236
+ // app/robots.js (Next.js App Router)
237
+ export default function robots() {
238
+ return {
239
+ rules: { userAgent: '*', allow: '/' },
240
+ sitemap: 'https://www.yourdomain.com/sitemap.xml',
241
+ };
242
+ }
243
+ ```
244
+
245
+ ---
246
+
247
+ ## Indexing Checklist
248
+
249
+ - [ ] All important pages have absolute canonical URLs
250
+ - [ ] No important pages accidentally noindexed
251
+ - [ ] Sitemap routes return 200 with valid XML
252
+ - [ ] Sitemap submitted to Google Search Console
253
+ - [ ] Important pages statically generated (●) in build output
254
+ - [ ] No redirect chains (A→B→C should be A→C)
255
+ - [ ] robots.txt allows important content
256
+ - [ ] Every important page has ≥1 internal inbound link
257
+ - [ ] `generateStaticParams` added for dynamic routes with known slugs
258
+
259
+ ## Limitations
260
+
261
+ - Does not guarantee Google will index a page; final indexing decisions remain with the search engine.
262
+ - Requires access to the codebase, deployed URLs, and ideally Google Search Console data for confident diagnosis.
263
+ - Treat recommendations that change URL structure, redirects, or canonical policy as production-impacting and review them before deployment.
@@ -9,6 +9,7 @@ if [[ ! -d "$target" ]]; then
9
9
  fi
10
10
 
11
11
  cd "$target"
12
+ repo_root="$(pwd -P)"
12
13
 
13
14
  status=0
14
15
 
@@ -21,6 +22,25 @@ warn() {
21
22
  status=1
22
23
  }
23
24
 
25
+ has_symlink_component() {
26
+ local candidate="$1"
27
+ local current="."
28
+ local part
29
+ local -a parts
30
+
31
+ candidate="${candidate#./}"
32
+ IFS='/' read -r -a parts <<< "$candidate"
33
+ for part in "${parts[@]}"; do
34
+ [[ -z "$part" || "$part" == "." ]] && continue
35
+ current="$current/$part"
36
+ if [[ -L "$current" ]]; then
37
+ return 0
38
+ fi
39
+ done
40
+
41
+ return 1
42
+ }
43
+
24
44
  if command -v rg >/dev/null 2>&1; then
25
45
  if rg --hidden --glob '!.git/**' --glob '!.github/workflows/**' --glob '!node_modules/**' --glob '!dist/**' --glob '!build/**' \
26
46
  --regexp 'ghp_[A-Za-z0-9_]{20,}' \
@@ -67,7 +87,29 @@ if command -v rg >/dev/null 2>&1 && [[ -f README.md ]]; then
67
87
  [[ "$link" =~ ^mailto: ]] && continue
68
88
  link="${link%%#*}"
69
89
  [[ -z "$link" ]] && continue
90
+ if [[ "$link" = /* || "/$link/" == *"/../"* ]]; then
91
+ broken_links=1
92
+ printf 'WARN README local link escapes repository: %s\n' "$link"
93
+ continue
94
+ fi
95
+ if has_symlink_component "$link"; then
96
+ broken_links=1
97
+ printf 'WARN README local link escapes repository: %s\n' "$link"
98
+ continue
99
+ fi
70
100
  if [[ ! -e "$link" ]]; then
101
+ parent_dir="$(dirname -- "$link")"
102
+ if [[ -d "$parent_dir" ]]; then
103
+ resolved_parent="$(cd "$parent_dir" && pwd -P)"
104
+ case "$resolved_parent/" in
105
+ "$repo_root"/* | "$repo_root/" ) ;;
106
+ * )
107
+ broken_links=1
108
+ printf 'WARN README local link escapes repository: %s\n' "$link"
109
+ continue
110
+ ;;
111
+ esac
112
+ fi
71
113
  broken_links=1
72
114
  printf 'WARN broken README local link: %s\n' "$link"
73
115
  fi
@@ -247,7 +247,8 @@ async function addImageAndWait(pea, imgURI) {
247
247
  count = (await pea.runScript(`app.echoToOE(app.activeDocument.layers.length)`))[0];
248
248
  count = parseInt(count);
249
249
 
250
- await pea.runScript(`app.open("${imgURI}", null, true);`);
250
+ const imageUrlLiteral = JSON.stringify(imgURI);
251
+ await pea.runScript(`app.open(${imageUrlLiteral}, null, true);`);
251
252
 
252
253
  return new Promise((resolve) => {
253
254
  const check = async () => {
@@ -306,9 +307,11 @@ document.getElementById("exportBtn").addEventListener("click", async () => {
306
307
  ```js
307
308
  async function generateCard(pea, name, tagline) {
308
309
  await pea.openFromURL("https://example.com/card.psd", false);
310
+ const nameLiteral = JSON.stringify(name);
311
+ const taglineLiteral = JSON.stringify(tagline);
309
312
  await pea.runScript(`
310
- app.activeDocument.layers.getByName("Name").textItem.contents = "${name}";
311
- app.activeDocument.layers.getByName("Tagline").textItem.contents = "${tagline}";
313
+ app.activeDocument.layers.getByName("Name").textItem.contents = ${nameLiteral};
314
+ app.activeDocument.layers.getByName("Tagline").textItem.contents = ${taglineLiteral};
312
315
  `);
313
316
  return await pea.exportImage("png");
314
317
  }
@@ -1385,6 +1388,7 @@ app.echoToOE(JSON.stringify(getLayerInfo(app.activeDocument)));
1385
1388
  - This skill covers host-page integration patterns; it does not replace Photopea's own terms, API documentation, or licensing guidance.
1386
1389
  - Remote URL loading depends on browser CORS behavior, network availability, and the user's Photopea account/session state.
1387
1390
  - `runScript` executes scripts inside the embedded Photopea document context. Only run scripts you understand and only with user-approved files.
1391
+ - Serialize dynamic values with `JSON.stringify` before embedding them in a `runScript` string. Never concatenate user-provided URLs, layer names, or text directly into Photopea script source.
1388
1392
  - Export behavior can vary by document size, browser memory limits, and the formats supported by the active Photopea runtime.
1389
1393
 
1390
1394
  ---