-
Notifications
You must be signed in to change notification settings - Fork 0
fix(public): land the TinyStudio document titles on /pricing and /brief-requested (kills the returned "The Tiny Studio" titles) #98
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
c685eaa
c6480b5
0ba96cc
5d1048a
fd00409
863a4da
5f1e883
bf15cc8
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -1547,6 +1547,63 @@ for (const [pageName, pageHtml, expected] of canonicalPages) { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // ---- Document titles (brand consistency) ---------------------------------- | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Two served pages still branded themselves "The Tiny Studio" — the spaced | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // name the site's own identity copy disavows (it collides with "The Tiny | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Studio LA" and other unrelated businesses) — while every other title said | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // "TinyStudio": /pricing served "Pricing & terms — The Tiny Studio" and | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // /brief-requested served "Request received — The Tiny Studio", both | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // byte-identical on origin/main. Title tags are a first-order SERP signal, so | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // every one of the six served appraisal pages must now name the brand in its | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // document title and must never return the spaced "The Tiny Studio" form. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // The retired /agent-desk surface is deliberately excluded: its title frames | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // itself as retired and it is noindex. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const titlePages = [ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ["homepage", siteHome], | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ["audit page", siteAudit], | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ["desk page", read("public/agents.html")], | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ["pricing page", read("public/pricing.html")], | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ["specimen page", read("public/specimen.html")], | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ["brief-requested page", read("public/brief-requested.html")] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ]; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| for (const [pageName, pageHtml] of titlePages) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const title = pageHtml.match(/<title>([^<]*)<\/title>/i)?.[1] ?? ""; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (!title) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| failures.push(`Document title must exist on ${pageName}.`); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| continue; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (!title.includes("TinyStudio")) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| failures.push(`Document title on ${pageName} must name TinyStudio (found ${JSON.stringify(title)}).`); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (title.includes("The Tiny Studio")) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
If a title regresses to a capitalization variant such as Useful? React with 👍 / 👎. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| failures.push(`Document title on ${pageName} must not use the spaced "The Tiny Studio" form (found ${JSON.stringify(title)}).`); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // ---- Intake field labels (activation) ------------------------------------- | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Both appraisal intake forms (homepage and /audit) labelled their fields | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // only with placeholder text, which disappears the moment a buyer starts | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // typing and is not a persistent programmatic label. Each intake input must | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // carry a non-empty aria-label so the field keeps its name for assistive | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // tech and for the browser's own validation announcements, no matter what | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // the field contains. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const intakePages = [ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ["homepage", siteHome], | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ["audit page", siteAudit] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ]; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| for (const [pageName, pageHtml] of intakePages) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| for (const input of pageHtml.matchAll(/<input\b[^>]*>/gi)) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const tag = input[0]; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (!/\bname="(?:website|email)"/.test(tag)) continue; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
If the email input is deleted or renamed on either intake page, this filter simply finds no email field and Useful? React with 👍 / 👎. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const aria = tag.match(/\baria-label="([^"]*)"/)?.[1] ?? ""; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+1599
to
+1600
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
If a live intake field is rewritten with single-quoted or differently cased attributes—both valid in HTML—this exact Useful? React with 👍 / 👎. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (!aria.trim()) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| failures.push(`Intake input on ${pageName} must carry a persistent programmatic aria-label (placeholder-only labels disappear as buyers type): ${tag}`); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+1596
to
+1603
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win Make the intake-field check fail closed. The loop validates only inputs that it finds. It does not fail when a required Track the expected field names, use format-tolerant attribute parsing, and fail when either expected field is absent or unlabeled. Suggested validation change for (const [pageName, pageHtml] of intakePages) {
+ const expectedNames = new Set(["website", "email"]);
+ const seenNames = new Set();
for (const input of pageHtml.matchAll(/<input\b[^>]*>/gi)) {
const tag = input[0];
- if (!/\bname="(?:website|email)"/.test(tag)) continue;
- const aria = tag.match(/\baria-label="([^"]*)"/)?.[1] ?? "";
+ const name = tag.match(/(?:^|\s)name\s*=\s*(["'])([\s\S]*?)\1/i)?.[2]?.toLowerCase();
+ if (!expectedNames.has(name)) continue;
+ seenNames.add(name);
+ const aria = tag.match(/(?:^|\s)aria-label\s*=\s*(["'])([\s\S]*?)\1/i)?.[2] ?? "";
if (!aria.trim()) {
failures.push(`Intake input on ${pageName} must carry a persistent programmatic aria-label (placeholder-only labels disappear as buyers type): ${tag}`);
}
}
+ for (const name of expectedNames) {
+ if (!seenNames.has(name)) {
+ failures.push(`Missing intake input on ${pageName}: ${name}.`);
+ }
+ }
}📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| for (const migration of ["migrations/0002_agent_runs.sql", "migrations/0003_agent_usage_limits.sql"]) { if (!existsSync(new URL(`../${migration}`, import.meta.url))) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| failures.push(`Missing migration: ${migration}`); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| continue; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If an editor leaves a branded
<title>TinyStudio…</title>inside an HTML comment before restoring a liveThe Tiny Studiotitle, this first-match regex selects the inert commented tag and the check passes even though the browser serves the stale branding. Strip HTML comments before matching—like the canonical check immediately above already does—and preferably inspect the live<head>content.Useful? React with 👍 / 👎.