--- name: shipcraft description: > Take a finished landing page and make it actually ship: a head that can be found and shared, a share card that survives the link preview, a close that converts instead of leaking, real proof, and a phone that works. The companion to scrollcraft: scrollcraft decides what the page feels like; shipcraft decides whether it works as a business asset. Use whenever a page is about to go live or has just gone live, and whenever someone says SEO, meta tags, frontmatter, Open Graph, OG image, link preview, share card, Google indexing, canonical, sitemap, structured data, schema, rich results, conversion, CTA, book a call, contact form, social proof, client logos, broken mobile layout, mobile navigation, or asks for a pre-launch or pre-deploy check. Also use immediately after a scrollcraft build and before deploying it, because a scroll page is especially likely to be beautiful and unfindable at the same time. allowed-tools: Bash, Read, Write, Edit, Glob, Grep, WebFetch --- # shipcraft A page can be the best thing you have ever built and still fail every job it was hired for. It fails if nobody can find it, if the link preview shows the wrong brand, if the one action leaks the visitor into an email client, if it asserts excellence with nothing to back it, or if it falls apart on the phone most people will open it on. scrollcraft governs everything inside the viewport. **Everything shipcraft governs is outside it**, which is exactly why it gets skipped: none of it shows up in the thing you spend all day looking at. ## The one idea Every concern here is a **floor**, not advice. Advice reads as a checklist, gets skimmed, and dies. A floor is mechanical, invisible in the design, and **can fail** — the same way scrollcraft's typography floor is not “consider tracking” but a measured value on a rendered page. Be precise about coverage. A claim of coverage that does not hold is worse than no claim: | Step | Asserted by `audit.mjs` | Needs your judgment | |---|---|---| | 1 · Head | Nearly all of it | Whether the copy is any good | | 2 · Share card | It exists, resolves, and matches its declared size | Whether it shows the right moment | | 3 · Conversion | Form semantics, dead anchors, mailto-only closes | Label consistency and a real submit test | | 4 · Proof | Nothing | Which claims are true, current, and cleared | | 5 · The phone | The viewport tag and zoom safety | Layout, nav, tap targets, focus, and the keyboard | | 6 · Gotchas | Nothing | All of it | **Steps 4 and 5 are the ones to be honest about.** No script can tell you a statistic is real or that a nav works under a thumb. Treat unasserted work with more suspicion, not less. Run the audit first: ```bash cd npm ci node scripts/audit.mjs --url http://localhost:4500 ``` It works against a local server or a live domain. It deliberately audits the raw HTTP response without executing JavaScript: link-preview bots commonly depend on that response, while search-engine rendering behavior varies. Raw HTML is the reliable floor even though Google can render JavaScript. What the script reports is the work list; the sections below explain how to fix it. Re-run it at the end. A build is done when it exits clean, not when the page merely looks right. Use `--prelaunch` only when the production canonical or sitemap cannot resolve yet. It downgrades those external availability checks to explicit warnings; it does not hide them. Run the default strict audit after deployment. **Assessing rather than fixing?** Everything here works read-only: run the audit, perform the manual checks in Steps 4 and 5, and report. Rendering a share card needs the repository because it reuses the project's stylesheet; say so instead of silently skipping it. ## What this skill refuses | Never | Why | |---|---| | Keyword density, content-length targets, or an FAQ bolted on for schema | Writing for a crawler instead of a person. The page's copy is the design. | | Structured data describing things the page does not contain | Misrepresentation. It can violate search-engine policies. | | Sticky CTA bars, exit-intent modals, countdown timers, or fake scarcity | Conversion by pressure. It reads as desperate and outlives its welcome on every scroll. | | A cookie banner nobody needed | Ship one only when the technologies used and applicable law require it. | | A keyword-stuffed hidden heading | Hidden text that contradicts the visible page is deceptive. Visually hidden text that accurately labels an interface is different. | | Chasing a Lighthouse score past real user benefit | The number is a proxy. Fix what the number is a proxy for. | The rule underneath: **a floor may never change what the page says to a person.** If a fix changes the visitor's experience, treat it as a design decision and review it accordingly. --- ## Step 1: The head Read [references/head.md](references/head.md). It contains a complete head block and the subtleties that cause most damage: - **Canonical must name the URL that actually resolves.** If the apex redirects to `www`, point the canonical to the final `www` URL. The strict audit fetches the canonical without following redirects and fails unless it returns `200` directly. That is a shipcraft floor stricter than the protocol minimum. - **Canonical signals must agree.** Canonical, `og:url`, primary JSON-LD page/site URL fields, and sitemap locations must use the chosen host. Canonical and `og:url` must identify the same page. - **Unknown paths must not answer with the homepage at `200`.** A catch-all rewrite can create soft-404 behavior. Single-page apps acquire this by accident because the rewrite that enables client routing can also make every typo look successful. ## Step 2: The share card Read [references/sharecard.md](references/sharecard.md). A scroll page is hard to preview. Twelve viewport-heights of choreography collapse, in Slack, LinkedIn, and messages, into one static image. For many people who encounter the link, that image **is** the page. Design the card as the first frame of the film. `scripts/sharecard.mjs` renders a 1200×630 PNG from the page's own stylesheet and fonts, so it inherits the brand instead of imitating it: ```bash node /scripts/sharecard.mjs \ --css site/oiika.css --out public/og-image.png \ --wordmark "Oiika" \ --tag "AI and agentic systems, built with your team" \ --line "You don't have to understand all of it." \ --foot-left "oiika.com" --foot-right "Toronto, Ontario" ``` The script writes both the PNG and a `.shipcraft.json` render manifest. Commit the manifest with the image so the card remains regenerable. The test: **the card should show the moment the tell-someone sentence describes.** If the brief says “the jargon sorts itself into one sentence,” show that sentence. A logo on a generic gradient could belong to anyone. ## Step 3: The close is the conversion Read [references/conversion.md](references/conversion.md). Two ideas carry this step: - **A CTA that leaves the page ends the visit.** `mailto:` is a fragile primary close: it can open an unconfigured mail client, provides no prompt, and moves the visitor into another application. Keep the primary conversion operable in place or route it to a deliberate, functioning booking flow. - **The ending disproportionately shapes the memory of the page.** Make the resolution be the conversion so the closing beat and primary action reinforce each other. The reference also covers the second ask at peak appetite, a friction-reducing sentence next to the button, and a short form that belongs on a premium page. ## Step 4: Proof Read [references/proof.md](references/proof.md). For anything sold on trust — consulting, services, B2B, expensive products — the journey needs a beat between substance and commitment: **validation**. Who has trusted this, and what can be named? Real-or-omitted is the rule. No script can verify truth or permission, so write down the manual review: - Every figure traces to a real source. Name it. - Every named client, testimonial, or logo is cleared to appear. - Every number carries attribution that makes it checkable in principle. - Nothing has quietly expired: a lapsed certification, former relationship, stale role, or figure that is no longer representative. ## Step 5: The phone Read [references/mobile.md](references/mobile.md). Desktop navigation decisions do not automatically survive a phone. A ten-viewport page with no way to jump becomes a tunnel. Load the page at 390×844, on a real device when possible, and confirm: - the hero does not wrap beyond two or three intentional lines - navigation exists, opens, closes, traps no one, and restores focus - the primary action is reachable without traversing the whole page - focusing each form field does not put it behind the virtual keyboard - important tap targets approach 44×44 CSS px; none violate the WCAG 2.2 AA 24×24 minimum or spacing exception - every lateral rail reaches its last item - fixed chrome does not cover content or focus indicators The audit asserts only the viewport and zoom-safety floor. Everything else requires a narrow rendered viewport and human interaction. ## Step 6: Re-audit, then read the gotchas Run `scripts/audit.mjs` again and get the default strict audit clean. Then read [references/gotchas.md](references/gotchas.md), a table of silent failures: the page renders, the console is empty, no automated check complains, and the experience is still broken. Examples include SVG dash behavior under `vector-effect` and `[hidden]` losing to an author `display` declaration. ## The report Say what the audit found, what changed, and what could not be verified. Always include: - the final command, URL, exit code, failures, and warnings - the proof sources and permission status that were manually checked - the phone sizes and input methods actually exercised - whether the form was submitted end to end and where the submission arrived - whether the share preview was refreshed in platform inspectors Two items deserve explicit mention because they often live outside the repo: - **Redirect permanence.** An apex-to-`www` redirect issued as `307` instead of `301`/`308` is often a hosting control-plane setting. Name it if unresolved. - **Search Console.** Sitemap submission, URL inspection, and reprocessing of retired URLs are authenticated human actions. Mark them pending unless they were actually completed. “Clean except two warnings, both listed” is honest. Silently passing by not looking is not. For the evidence behind the floors and their deliberate limits, read [references/sources.md](references/sources.md).