Skip to content

SEO: add truthful page meta descriptions - #21

Merged
nish3451 merged 2 commits into
mainfrom
fix/meta-descriptions
Aug 8, 2026
Merged

SEO: add truthful page meta descriptions#21
nish3451 merged 2 commits into
mainfrom
fix/meta-descriptions

Conversation

@nish3451

@nish3451 nish3451 commented Aug 8, 2026

Copy link
Copy Markdown
Collaborator

intended-outcome: Add one concise, page-specific meta description to each of the five public pages so search previews identify the existing Website Appraisal offer accurately.

verify: /home/nish/.local/bin/test-gate npm run check; /home/nish/.local/bin/test-gate npm test; git diff --check; sgscan

Repository proof only. No live deployment, live search-impact, ranking, traffic, or conversion improvement is claimed. No deployment or merge in this change.

Summary by CodeRabbit

  • Documentation

    • Added concise, search-friendly descriptions for the homepage, specialists, audit, pricing, and specimen pages to improve search result previews.
  • Tests

    • Added site checks to verify each page has one unique, non-empty meta description within the recommended length and without prohibited promotional claims.
    • Validation now flags missing, duplicate, empty, oversized, or promotional descriptions.

Co-Authored-By: Claude <noreply@anthropic.com>

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nish3451 has reached the 50-credit limit for trial accounts. To continue receiving code reviews, upgrade your plan.

@coderabbitai

coderabbitai Bot commented Aug 8, 2026

Copy link
Copy Markdown

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: b1b07ba8-7975-4ff8-a28e-c541a38dad5f

📥 Commits

Reviewing files that changed from the base of the PR and between 96b7e9f and 19ad42d.

📒 Files selected for processing (6)
  • public/agents.html
  • public/audit.html
  • public/index.html
  • public/pricing.html
  • public/specimen.html
  • scripts/check-site.mjs

📝 Walkthrough

Walkthrough

Five public pages now include descriptive meta tags. scripts/check-site.mjs validates that each page has one unique, non-empty description within 160 characters and without forbidden claims.

Changes

Public metadata validation

Layer / File(s) Summary
Page metadata and validation
public/agents.html, public/audit.html, public/index.html, public/pricing.html, public/specimen.html, scripts/check-site.mjs
The five public pages add meta descriptions. Site checks validate uniqueness, length, non-empty content, and forbidden claims.

Estimated code review effort: 2 (Simple) | ~10 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: adding truthful meta descriptions to public pages.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/meta-descriptions

Comment @coderabbitai help to get the list of available commands.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 96b7e9f4df

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread public/specimen.html
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="The appraisal, with the client's name removed: a real audit of a clinic homepage, four findings with evidence and fixes, read and signed by Nish.">

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Describe the specimen as non-client research

When this description is consumed by a crawler or shown as a search snippet, “the client's name removed” presents the specimen as anonymized client work. The page explicitly states that the clinic is not a client and that the audit comes from public-homepage research, so the new metadata creates the proof claim the page disclaims; describe it as an unnamed clinic instead.

AGENTS.md reference: AGENTS.md:L2-L3

Useful? React with 👍 / 👎.

Comment thread scripts/check-site.mjs

const seenDescriptions = new Map();
for (const [pageName, pageHtml] of metaDescriptionPages) {
const tags = [...pageHtml.matchAll(/<meta\b[^>]*\bname="description"[^>]*>/gi)].map((match) => match[0]);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Restrict the description search to the head

If a description is accidentally moved below </head> while remaining elsewhere in the document, this whole-document regex still finds exactly one tag and the check passes, even though the invariant and failure message require metadata in the head. Extract or otherwise bound the search to the document's <head> so this regression is actually detected.

Useful? React with 👍 / 👎.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@public/index.html`:
- Line 6: Update the description meta tag content in the document head so the
phrase “Six a month” explicitly states the unit as “Six audits a month,” while
preserving the rest of the description.

In `@scripts/check-site.mjs`:
- Around line 785-787: Update the meta-description matcher in the site-check
logic around the tags collection so it first restricts matching to the
document’s <head> content and only recognizes the exact name="description"
attribute, excluding body elements and data-name attributes. Preserve the
existing exactly-one validation and failure message.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: a4282970-d7d5-4ff2-81fc-71a30b7085fe

📥 Commits

Reviewing files that changed from the base of the PR and between 6172ef9 and 96b7e9f.

📒 Files selected for processing (6)
  • public/agents.html
  • public/audit.html
  • public/index.html
  • public/pricing.html
  • public/specimen.html
  • scripts/check-site.mjs

Comment thread public/index.html
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="TinyStudio: the free leak audit of high-ticket service homepages. Each fault named in order of what it costs you, with the fix beside it. Six a month.">

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail
rg -n -C 3 -- 'Six a month|six|a month|\$2,500|three-month minimum' public/index.html public/pricing.html || true

Repository: nish3451/TinyStudio.io

Length of output: 8317


State the unit in Six a month.

If this refers to audit capacity, change it to Six audits a month. The meta description can appear without the page context, so the current wording is ambiguous with the $2,500 monthly desk price.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@public/index.html` at line 6, Update the description meta tag content in the
document head so the phrase “Six a month” explicitly states the unit as “Six
audits a month,” while preserving the rest of the description.

Comment thread scripts/check-site.mjs
Comment on lines +785 to +787
const tags = [...pageHtml.matchAll(/<meta\b[^>]*\bname="description"[^>]*>/gi)].map((match) => match[0]);
if (tags.length !== 1) {
failures.push(`Meta description must appear exactly once in the head of ${pageName} (found ${tags.length}).`);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail
node <<'NODE'
const pattern = /<meta\b[^>]*\bname="description"[^>]*>/gi;
const samples = [
  '<html><head></head><body><meta name="description" content="body"></body></html>',
  '<head><meta data-name="description" content="wrong"></head>',
];
for (const sample of samples) {
  console.log([...sample.matchAll(pattern)].length);
}
NODE

Repository: nish3451/TinyStudio.io

Length of output: 164


🏁 Script executed:

#!/bin/bash
set -euo pipefail
printf '%s\n' '--- plan candidates ---'
git ls-files | rg -i '(^|/)(plan|plans|readme|agents|contributing)(\.|/|$)|(^|/).*plan.*\.(md|txt)$' | head -80
printf '%s\n' '--- target context ---'
cat -n scripts/check-site.mjs | sed -n '760,815p'
printf '%s\n' '--- related head parsing and checks ---'
rg -n -C 3 'matchAll|<head|description|pageHtml' scripts/check-site.mjs

Repository: nish3451/TinyStudio.io

Length of output: 6877


🏁 Script executed:

#!/bin/bash
set -euo pipefail
printf '%s\n' '--- repository instructions ---'
cat AGENTS.md
printf '%s\n' '--- current plan candidates ---'
for f in docs/plans/2026-06-18-002-fix-minimal-input-agent-desk-plan.md specs/003-wellness-clinic-launch/plan.md; do
  if [ -f "$f" ]; then
    printf '\n### %s\n' "$f"
    cat "$f"
  fi
done
printf '%s\n' '--- page source locations ---'
sed -n '1,130p' scripts/check-site.mjs
printf '%s\n' '--- all description tags in checked page files ---'
rg -n -i '<meta[^>]*(name|data-name)[^>]*description|description[^>]*>' public/*.html
printf '%s\n' '--- verifier: current matcher versus proposed matcher ---'
node <<'NODE'
const current = /<meta\b[^>]*\bname="description"[^>]*>/gi;
const proposedHead = /<head\b[^>]*>([\s\S]*?)<\/head>/i;
const proposedTag = /<meta\b(?=[^>]*\sname\s*=\s*"description"(?:\s|>))[^>]*>/gi;
const samples = [
  '<html><head></head><body><meta name="description" content="body"></body></html>',
  '<head><meta data-name="description" content="wrong"></head>',
  '<head><meta name="description" content="valid"></head>',
  '<head><meta class="x" name = "description" content="valid"></head>',
  '<head><meta name="description" content="valid"><meta name="description" content="duplicate"></head>',
];
for (const sample of samples) {
  const head = sample.match(proposedHead)?.[1] ?? '';
  console.log(JSON.stringify({
    sample,
    current: [...sample.matchAll(current)].length,
    proposed: [...head.matchAll(proposedTag)].length,
  }));
}
NODE

Repository: nish3451/TinyStudio.io

Length of output: 25129


Restrict the meta-description check to <head>.

The current regex scans the full document and treats data-name="description" as a match. A body element or data-name attribute can satisfy the head-description check.

Suggested matcher change
-  const tags = [...pageHtml.matchAll(/<meta\b[^>]*\bname="description"[^>]*>/gi)].map((match) => match[0]);
+  const head = pageHtml.match(/<head\b[^>]*>([\s\S]*?)<\/head>/i)?.[1] ?? "";
+  const tags = [...head.matchAll(/<meta\b(?=[^>]*\sname\s*=\s*"description"(?:\s|>))[^>]*>/gi)].map((match) => match[0]);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const tags = [...pageHtml.matchAll(/<meta\b[^>]*\bname="description"[^>]*>/gi)].map((match) => match[0]);
if (tags.length !== 1) {
failures.push(`Meta description must appear exactly once in the head of ${pageName} (found ${tags.length}).`);
const head = pageHtml.match(/<head\b[^>]*>([\s\S]*?)<\/head>/i)?.[1] ?? "";
const tags = [...head.matchAll(/<meta\b(?=[^>]*\sname\s*=\s*"description"(?:\s|>))[^>]*>/gi)].map((match) => match[0]);
if (tags.length !== 1) {
failures.push(`Meta description must appear exactly once in the head of ${pageName} (found ${tags.length}).`);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/check-site.mjs` around lines 785 - 787, Update the meta-description
matcher in the site-check logic around the tags collection so it first restricts
matching to the document’s <head> content and only recognizes the exact
name="description" attribute, excluding body elements and data-name attributes.
Preserve the existing exactly-one validation and failure message.

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nish3451 has reached the 50-credit limit for trial accounts. To continue receiving code reviews, upgrade your plan.

@nish3451
nish3451 merged commit c0862d4 into main Aug 8, 2026
2 of 3 checks passed
nish3451 added a commit that referenced this pull request Aug 8, 2026
…c10709

The meta-description fix for the home page (and the other four public
pages) was merged as PR #21, with a source-string CI guard in
check-site.mjs, but the live deployment was never measured. This closes
that gap by recording a real-Chromium measurement of the five deployed
tinystudio.io pages (2026-08-09): each serves exactly one non-empty,
unique meta description in its head within search-snippet length, with no
duplicates and no console errors. Dogfood finding 18dd05c10709 (missing
meta description on home) is verified resolved on the deployed site.
nish3451 added a commit that referenced this pull request Aug 8, 2026
…c10709 (#26)

The meta-description fix for the home page (and the other four public
pages) was merged as PR #21, with a source-string CI guard in
check-site.mjs, but the live deployment was never measured. This closes
that gap by recording a real-Chromium measurement of the five deployed
tinystudio.io pages (2026-08-09): each serves exactly one non-empty,
unique meta description in its head within search-snippet length, with no
duplicates and no console errors. Dogfood finding 18dd05c10709 (missing
meta description on home) is verified resolved on the deployed site.
nish3451 added a commit that referenced this pull request Aug 9, 2026
…st current main and live (#37)

The code-side fix (PR #21) and CI enforcement (the 'Meta descriptions
(dogfood)' guard in scripts/check-site.mjs) for dogfood finding
18dd05c10709 ('Missing meta description on home') are already merged in
origin/main. This lane re-verified the guarantee still holds after the
subsequent page edits (heading hierarchy, apple-touch icon, schema.org,
canonical URLs, internal-link cleanup, App Store citation, sitemap):

- npm run check passes on all five public pages: each carries exactly one
  non-empty description tag in its head, within a search-snippet length
  (<= 160 chars), distinct per page, free of forbidden promises.
- Fresh live measurement of the deployed pages in real Chromium confirms
  the same: exactly one valid, non-empty, unique meta description per page,
  including the home page the finding flagged (150 chars).

Nothing further to change; the receipt now records the closeout on the
current head so the finding cannot be re-opened by tracker drift.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant