diff --git a/docs/launch-checklist.md b/docs/launch-checklist.md index a10157d..f99b511 100644 --- a/docs/launch-checklist.md +++ b/docs/launch-checklist.md @@ -28,7 +28,7 @@ Status legend: `[ ]` open ยท `[x]` done ยท `[?]` needs verification ยท ๐Ÿ›‘ owne | Search | Google Search Console domain property verified; sitemap submitted and fetched by Googlebot | | Mail | MXroute. SPF pass, DKIM pass (selector `x`), DMARC `p=none` โ€” mail-tester 9.5/10 | | `npm run build` / `typecheck` / `seo:lint` | green, 21 pages | -| `npm run test:e2e` | 44 passed / 4 failed โ€” stale assertions, see ยง2.1 | +| `npm run test:e2e` | **48/48 green** | ### Traffic path ``` @@ -79,32 +79,21 @@ discovered 2026-10-23. - [ ] Durable fix in the `gitea` ansible role: disable live-restore on that VM, or restart the runner after dockerd restarts (systemd `PartOf=`/`ExecStartPost` hook). -### 1.4 `/insights/` ships empty, with developer-facing copy ๐Ÿ›‘ -`src/pages/insights/index.astro` shows two cards written for a developer ("Publishing path", -"RSS support") and a hero calling the section a "Future publishing home". The section is in the -primary nav with zero articles. -- [ ] ๐Ÿ›‘ Ship it or not. -- [ ] If yes: delete both note-cards and rewrite the hero as reader-facing copy. -- [ ] If no: drop it from the primary nav and exclude the route from the sitemap. +### 1.4 `/insights/` โœ… 2026-10-23 +Now a reader-facing "Coming soon" page (hero + contact CTA); the developer-facing cards are gone. +It stays in the nav. When the first real article lands, restore a listing on this page. -### 1.5 Privacy policy review ๐Ÿ›‘ -`/privacy/` went live 2026-10-23, drafted from what the site actually does (contact form via -Formspree, Umami, GA4 with cookies, server/security logs). -- [ ] ๐Ÿ›‘ Owner review of the text. It is a legal document. -- [ ] ๐Ÿ›‘ Consent banner: GA4 sets cookies. Strictly, EU/UK visitors need opt-in consent; most - US-focused small-business sites run with a privacy policy only. Owner's call. Umami needs - neither. -- Anything added to `src/components/Analytics.astro` must be disclosed on `/privacy/`. +### 1.5 Privacy policy โœ… 2026-10-23 +`/privacy/` reviewed and accepted by the owner. No consent banner (owner's call). +Anything added to `src/components/Analytics.astro` must be disclosed on `/privacy/`. --- ## 2. Should fix -### 2.1 e2e suite is red โ€” stale assertions, not a regression -4 of 48 fail (2 tests ร— desktop/mobile). Both assert **copy the exact-copy work correctly removed**: -- `tests/site.spec.ts:63` waits for a link named `Explore services`; the homepage CTA is `All services`. -- `tests/site.spec.ts:93` waits for a heading matching `/Focused expertise/`, gone from `/focus-areas/`. -- [ ] Update both tests to current copy; get back to green so the suite is trustworthy. +### 2.1 e2e suite โœ… green 2026-10-23 โ€” 48/48 +The stale assertions (invented copy removed by the exact-copy work) now check the real headings +and use the header Services link; the homepage body has no direct `/services/` link. ### 2.2 Repo hygiene Commit `9f1cbca` committed ~50 `.playwright-mcp/` screenshots/snapshots plus a 2.8 MB @@ -122,11 +111,13 @@ Commit `9f1cbca` committed ~50 `.playwright-mcp/` screenshots/snapshots plus a 2 - [x] **Canonical host** โ€” `www` (2026-10-23). Apex 301s via Traefik middleware in `k8s/ingress.yaml`. - [x] **Analytics** โ€” Umami + GA4 side by side (2026-10-23). - [ ] ๐Ÿ›‘ **Contact details** โ€” confirm `804-332-6618` / `info@bluecapstrategies.com` are final. -- [ ] ๐Ÿ›‘ **AI training-bot policy** โ€” `GPTBot` and `ClaudeBot` are **Allow: /** in - `public/robots.txt`, with a ready-to-uncomment `Disallow: /`. The site is now crawlable. +- [x] **AI training-bot policy** โ€” training crawlers blocked (2026-10-23): GPTBot, ClaudeBot, + Google-Extended, CCBot, Applebot-Extended, meta-externalagent, Bytespider. Search and + AI answer/search crawlers (Googlebot, Bingbot, OAI-SearchBot, Claude-SearchBot, โ€ฆ) stay allowed. - [ ] ๐Ÿ›‘ **Brad Rodgers bio + credentials + portrait** โ€” gates `Person` schema, the About buildout, and principal-led E-E-A-T/GEO positioning. -- [ ] ๐Ÿ›‘ **Real insights articles** โ€” no fabricated or unreviewed AI content (see ยง1.4). +- [ ] ๐Ÿ›‘ **Real insights articles** โ€” no fabricated or unreviewed AI content. `/insights/` is + "Coming soon" until the first one exists (ยง1.4). - [ ] ๐Ÿ›‘ **Social profiles** โ€” provide real profiles or omit the footer block. - [ ] ๐Ÿ›‘ **Proof modules / representative engagements** โ€” no fabricated client work. diff --git a/public/robots.txt b/public/robots.txt index ff5f050..c99a045 100644 --- a/public/robots.txt +++ b/public/robots.txt @@ -1,8 +1,6 @@ # BlueCap Strategies robots.txt โ€” see docs/seo-aeo-optimization.md ยง5 # Policy: allow classic search + AI answer/search crawlers for maximum discoverability and -# answer-engine citation. Training-crawler policy (GPTBot, ClaudeBot, Google-Extended) is an -# owner decision โ€” currently ALLOWED for maximum reach. To opt out of model training, uncomment -# the "Disallow: /" lines in the training-crawler block below. +# answer-engine citation. Model-TRAINING crawlers (GPTBot, ClaudeBot, Google-Extended, โ€ฆ) are BLOCKED (owner decision, 2026-10-23). # --- Classic search engines --- User-agent: Googlebot @@ -27,19 +25,29 @@ Allow: / User-agent: PerplexityBot Allow: / -# Google-Extended controls Gemini + Google AI Overviews (this is also a training signal for -# Google โ€” treated as answer-visibility here; move to the training block to opt out). -User-agent: Google-Extended -Allow: / - -# --- AI model-training crawlers (owner decision โ€” allowed by default) --- +# --- AI model-training crawlers โ€” blocked (owner decision, 2026-10-23) --- User-agent: GPTBot -Allow: / -# Disallow: / +Disallow: / User-agent: ClaudeBot -Allow: / -# Disallow: / +Disallow: / + +User-agent: CCBot +Disallow: / + +User-agent: Applebot-Extended +Disallow: / + +User-agent: meta-externalagent +Disallow: / + +User-agent: Bytespider +Disallow: / + +# Google-Extended is Google's opt-out for Gemini training/grounding only. Google Search and AI +# Overviews are governed by Googlebot (allowed above), so blocking this does not affect search. +User-agent: Google-Extended +Disallow: / # --- Everything else --- User-agent: * diff --git a/src/pages/insights/index.astro b/src/pages/insights/index.astro index db4bff9..09a38c2 100644 --- a/src/pages/insights/index.astro +++ b/src/pages/insights/index.astro @@ -5,7 +5,7 @@ import ContactCta from "@components/ContactCta.astro"; import { breadcrumbSchema, pageSchema } from "@utils/schema"; const description = - "A prepared future publishing section for BlueCap Strategies articles, essays, case studies, market notes, and announcements."; + "Articles, analysis, and updates from BlueCap Strategies are coming soon."; --- -
-
-

Publishing path

-

- Future posts can be added as Markdown or MDX in src/content/insights with - typed frontmatter for title, description, publish date, modified date, tags, and optional - canonical URL. -

-
-
-

RSS support

-

- RSS is available at /rss.xml. The feed is ready for future article - imports even though no public posts are published yet. -

-
-
diff --git a/tests/site.spec.ts b/tests/site.spec.ts index b19edf8..2fa287c 100644 --- a/tests/site.spec.ts +++ b/tests/site.spec.ts @@ -64,14 +64,14 @@ test("desktop navigation and CTA links are clickable", async ({ page }) => { await page.setViewportSize({ width: 1440, height: 900 }); await page.goto("/"); - await page.getByRole("link", { name: "Explore services" }).click(); + await page.getByRole("banner").getByRole("link", { name: "Services", exact: true }).first().click(); await expect(page).toHaveURL(/\/services\/$/); - await expect(page.getByRole("heading", { name: /Advisory services/ })).toBeVisible(); + await expect(page.getByRole("heading", { level: 1, name: "Services" })).toBeVisible(); await page.goto("/"); await page.getByRole("link", { name: "Request a consultation" }).first().click(); await expect(page).toHaveURL(/\/contact\/$/); - await expect(page.getByRole("heading", { name: /Get in touch/ })).toBeVisible(); + await expect(page.getByRole("heading", { level: 1, name: "Contact Us" })).toBeVisible(); }); test("service and focus-area learn more links are wired to detail pages", async ({ page }) => { @@ -98,7 +98,7 @@ test("mobile menu opens and navigates", async ({ page }) => { await expect(page.locator(".mobile-nav nav")).toBeVisible(); await page.locator(".mobile-nav").getByRole("link", { name: "Focus Areas" }).click(); await expect(page).toHaveURL(/\/focus-areas\/$/); - await expect(page.getByRole("heading", { name: /Focused expertise/ })).toBeVisible(); + await expect(page.getByRole("heading", { level: 1, name: "Core Focus Areas" })).toBeVisible(); }); test("contact form validates required, invalid, and valid paths", async ({ page }) => {