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.
- package/bundled-skills/.antigravity-install-manifest.json +14 -1
- package/bundled-skills/bilig-workpaper/SKILL.md +12 -3
- package/bundled-skills/bumblebee/SKILL.md +6 -2
- package/bundled-skills/bun-development/SKILL.md +5 -3
- package/bundled-skills/cloud-penetration-testing/SKILL.md +5 -3
- package/bundled-skills/container-security-hardening/SKILL.md +1001 -0
- package/bundled-skills/container-security-hardening/references/base-image-comparison.md +245 -0
- package/bundled-skills/container-security-hardening/references/kubernetes-pod-security.md +567 -0
- package/bundled-skills/container-security-hardening/references/seccomp-profile-template.json +337 -0
- package/bundled-skills/doc2math/SKILL.md +102 -0
- package/bundled-skills/docs/integrations/jetski-cortex.md +3 -3
- package/bundled-skills/docs/integrations/jetski-gemini-loader/README.md +1 -1
- package/bundled-skills/docs/maintainers/repo-growth-seo.md +3 -3
- package/bundled-skills/docs/maintainers/skills-update-guide.md +1 -1
- package/bundled-skills/docs/users/bundles.md +1 -1
- package/bundled-skills/docs/users/claude-code-skills.md +1 -1
- package/bundled-skills/docs/users/gemini-cli-skills.md +1 -1
- package/bundled-skills/docs/users/getting-started.md +6 -2
- package/bundled-skills/docs/users/kiro-integration.md +1 -1
- package/bundled-skills/docs/users/usage.md +4 -4
- package/bundled-skills/docs/users/visual-guide.md +4 -4
- package/bundled-skills/environment-setup-guide/SKILL.md +10 -6
- package/bundled-skills/evolution/SKILL.md +5 -3
- package/bundled-skills/github-actions-advanced/SKILL.md +1100 -0
- package/bundled-skills/gitops-workflow/SKILL.md +5 -3
- package/bundled-skills/ii-commons/SKILL.md +15 -1
- package/bundled-skills/lemmaly/SKILL.md +15 -6
- package/bundled-skills/linkerd-patterns/SKILL.md +5 -3
- package/bundled-skills/longbridge/SKILL.md +95 -0
- package/bundled-skills/mercury-mcp/SKILL.md +9 -1
- package/bundled-skills/moatmri/SKILL.md +84 -0
- package/bundled-skills/nextjs-seo-indexing/SKILL.md +263 -0
- package/bundled-skills/openclaw-github-repo-commander/scripts/repo-audit.sh +42 -0
- package/bundled-skills/photopea-embedded-editor/SKILL.md +7 -3
- package/bundled-skills/runaway-guard/SKILL.md +331 -0
- package/bundled-skills/schema-markup-generator/SKILL.md +319 -0
- package/bundled-skills/sendblue/sendblue-api/SKILL.md +6 -1
- package/bundled-skills/sendblue/sendblue-cli/SKILL.md +6 -1
- package/bundled-skills/sendblue/sendblue-notify/SKILL.md +6 -1
- package/bundled-skills/sendblue/textme/SKILL.md +4 -0
- package/bundled-skills/social-metadata-hardening/SKILL.md +230 -0
- package/bundled-skills/socialclaw/SKILL.md +6 -1
- package/bundled-skills/uv-package-manager/resources/implementation-playbook.md +5 -3
- package/bundled-skills/varlock/SKILL.md +10 -6
- package/bundled-skills/vibe-code-cleanup/SKILL.md +231 -0
- package/bundled-skills/vibecode-production-qa-validator/SKILL.md +237 -0
- package/bundled-skills/wordpress-centric-high-seo-optimized-blogwriting-skill/SKILL.md +229 -162
- package/bundled-skills/yield-intelligence/SKILL.md +121 -0
- package/bundled-skills/youtube-full/SKILL.md +144 -0
- package/package.json +1 -1
- 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
|
-
|
|
145
|
-
|
|
146
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
#
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
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
|
-
|
|
77
|
-
|
|
78
|
-
|
|
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:
|
|
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
|
-
|
|
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 =
|
|
311
|
-
app.activeDocument.layers.getByName("Tagline").textItem.contents =
|
|
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
|
---
|