git clone --depth 1 https://github.com/modu-ai/moai-adk /tmp/moai-ref-seo && cp -r /tmp/moai-ref-seo/.claude/skills/moai-ref-seo ~/.claude/skills/moai-ref-seoSKILL.md
# Search Visibility Reference ## Target Agents - `manager-develop` — applies these rules while implementing pages, routes, and serialized metadata output - `/moai review` — pre-ship indexing review surface; equivalently available as a per-spawn `Agent(general-purpose)` with web-output review instructions ## Core Principle A page is indexed on what a machine can fetch and parse, not on what a person sees once everything has finished loading. Two failures dominate everything below: the same content reachable at more than one address, and a claim asserted in serialized data that nothing on the page corroborates. Every rule here is a specialization of one of those two. Figures that engines publish and then quietly revise — truncation widths, ranking weights, crawl allowances — are deliberately absent. Where a limit matters, this reference gives the decision rule and the measurement to take, so the guidance outlives the figure. ## Document Semantics The structure a parser reads before it reaches any content signal. Cheapest class of defect to introduce, and the cheapest to detect. | Rule | How to check it | Failure it prevents | |---|---|---| | Exactly one `h1` per document | Count `h1` elements in the rendered output of each page | Competing topic signals leave the subject ambiguous | | No skipped heading level | Walk the heading sequence; each descent moves by at most one level | Section nesting a parser cannot reconstruct | | Every image carries `alt` text | Each image element has a non-empty `alt` attribute, or an empty one paired with an explicit decorative marker | Meaning locked inside a binary the parser cannot open | | Anchor text names its destination | Read each link's text with the surrounding sentence hidden, then ask where it goes | Instruction-shaped link text carries no signal about the target | | Fragment targets resolve | For each in-page fragment link, confirm a matching identifier exists in the same rendered output | Navigation that silently lands nowhere | Derive `alt` text from what the image depicts, never from its file name. Where an image genuinely adds nothing a reader needs, mark it decorative on purpose instead of inventing a description for it. ## Identity and Canonical Address One resource, one address; everything else redirects to it. | Decision | Rule | |---|---| | Which address is canonical | Pick one form per resource and declare it. The declared value must equal the address actually served | | Trailing-slash variants | Choose one form and redirect the other permanently. Serving both splits one resource across two addresses | | Case, query parameters, tracking suffixes | Normalize before serving. A parameter that does not change the response must not mint a second address | | Parameterized routes | Build the declared value from the resolved parameters, never from a fixed string shared across the whole route | | Retiring an address | Redirect permanently from the old form and update the declaration in the same change | A declaration pointing at an address that redirects, errors, or serves different content is worse than no declaration at all: it actively steers the reader away from the page it appears on. ## Per-Page Metadata | Field | Rule | Recurring defect | |---|---|---| | `title` | Unique per page, composed from a page-specific part plus a stable identifier for the site | The scaffold's default survives to production on every route | | meta description | Unique per page, written for a person reading a result snippet | One description copied everywhere, or prose that describes nothing | | Indexing directive | Set a default for public pages, then narrow per page class. Authenticated areas and internal tools are excluded deliberately, not merely left unlinked | A private surface gets indexed because nothing declared otherwise | | Social preview fields | Present and absolute. A relative address in a field a third party fetches resolves against the wrong host | A share card that renders blank off-site | Length budgets are a decision rule, not a constant: draft the text, observe where the consuming surface truncates it, then cut to what you observed. Placeholder detection belongs in the pre-ship check — scan the emitted output for the scaffold's own default strings and fail when one survives. ## Structured Data Serialized JSON-LD states what a page *is*. Its one hard constraint is correspondence with the visible page. | Decision | Rule | |---|---| | Which types to emit | Derive them from the page's actual role — an organization, a product, a piece of software, a place, an article. Emit the site-level type everywhere and the page-specific type only where it applies | | Required fields | Each type has a small mandatory core. Emit that core completely rather than emitting several types partially | | Addresses inside the data | Absolute, and resolving. Relative values are discarded without a warning | | Several entities on one page | Emit one block holding all of them, give each a stable identifier, and cross-reference by identifier instead of nesting duplicate copies | | Placement | Keep each type on the page it describes. A type repeated site-wide dilutes rather than reinforces | **Mirroring rule** — every claim in the serialized data needs a visible counterpart on the same page. A name, a description, a rating, or a question-and-answer pair that exists only in the markup is an assertion the reader cannot check, and it is now scored as a negative signal rather than a neutral one. ## Entity Consistency Structured data identifies an entity. Consistency is what makes that identity hold across independent sources. | Surface | Requirement | |---|---| | Canonical name | One spelling, one casing, one suffix — the same in the serialized data, the page copy, and the headings | | Owned profile links | Restricted to accounts this entity itself administers, each confirmed to resolve rather than bounce to a sign-in wall | | Contact details | Name, addr
Claude Code upstream change tracker -> moai-adk update plan + docs sync workflow (dev-only). Tracks new CC release notes, classifies changes by impact tier, cross-references official docs, generates update plan at .moai/research/ or .moai/specs/, and synchronizes docs-site 4-locale + README. NOT distributed to user projects.
GitHub Workflow - Manage issues and review PRs with Agent Teams (dev-only). NOT distributed to user projects.
MoAI-ADK production release via Enhanced GitHub Flow (CLAUDE.local.md §18). Creates release/vX.Y.Z branch, version bump, CHANGELOG (bilingual), PR to main, merge commit (NOT squash), then scripts/release.sh for tag + GoReleaser. Hotfix support via --hotfix flag. All git operations delegated to manager-git. Quality failures escalate to expert-debug. NOT distributed to user projects (dev-only).
Run the 7-phase /moai brain ideation workflow to convert ideas into validated proposals
Identify and safely remove dead code with test verification
Scan codebase and generate architecture documentation in codemaps/
Analyze test coverage, identify gaps, and generate missing tests
Hybrid design workflow — Claude Design import (path A) or code-based brand design (path B)