fix(public): persistent labels on both appraisal intake fields and brand-consistent document titles on /pricing and /brief-requested - #67
Conversation
…kill the two "The Tiny Studio" document titles The homepage and /audit intake forms labelled their fields only with placeholder text, which disappears the moment a buyer starts typing and is not a persistent programmatic label; both served pages now carry a stable aria-label on the website and email inputs. /pricing and /brief-requested still branded their document titles "The Tiny Studio" — the spaced name the site's own identity copy disavows — while every other page said TinyStudio; both titles now match the brand (and the pricing title matches its own og:title). Two deterministic guards in check-site.mjs make both regressions impossible: every one of the six served appraisal titles must name TinyStudio and never "The Tiny Studio", and every intake website/email input must carry a non-empty aria-label. The retired /agent-desk page is excluded deliberately: its title frames itself as retired and it is noindex. verify: npm run check
There was a problem hiding this comment.
nish3451 has reached the 50-credit limit for trial accounts. To continue receiving code reviews, upgrade your plan.
|
Warning Review limit reached
Next review available in: 58 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (1)
📝 WalkthroughWalkthroughThe pull request standardizes TinyStudio page titles, adds accessible labels to homepage and audit intake inputs, and extends ChangesBranding and accessibility validation
Estimated code review effort: 2 (Simple) | ~10 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 45552528f8
ℹ️ 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".
| ]; | ||
|
|
||
| for (const [pageName, pageHtml] of titlePages) { | ||
| const title = pageHtml.match(/<title>([^<]*)<\/title>/i)?.[1] ?? ""; |
There was a problem hiding this comment.
Ignore inert titles before validating the document title
When a page contains an earlier commented-out title such as <!-- <title>TinyStudio — old</title> -->, this raw-source regex selects that match and can let a missing or misbranded live title pass the check. Strip HTML comments and inspect the <head>—as the canonical check immediately above already does—before asserting the title, ideally also verifying that exactly one live title exists.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 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 `@scripts/check-site.mjs`:
- Around line 1541-1547: Update the intake input validation loop in the
site-check logic to parse HTML attributes with flexible whitespace and either
single or double quotes, so both name and aria-label values are recognized.
Track matching fields per page and add failures when the expected website and
email inputs are absent, while preserving the existing requirement for non-empty
programmatic aria-labels.
🪄 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: bacbbf26-7293-4d58-bc95-a3e849acb60d
📒 Files selected for processing (5)
public/audit.htmlpublic/brief-requested.htmlpublic/index.htmlpublic/pricing.htmlscripts/check-site.mjs
| 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; | ||
| const aria = tag.match(/\baria-label="([^"]*)"/)?.[1] ?? ""; | ||
| if (!aria.trim()) { | ||
| failures.push(`Intake input on ${pageName} must carry a persistent programmatic aria-label (placeholder-only labels disappear as buyers type): ${tag}`); |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Make the intake-field check robust to valid HTML syntax.
Lines 1542-1547 only recognize exact double-quoted name and aria-label attributes. A valid name='website' input is skipped, and a valid aria-label='...' value is reported as missing. The loop also passes when a page has no matching inputs. Use a quote- and whitespace-tolerant matcher or parser, and assert that each page contains the expected website and email fields.
Proposed matcher fix
- if (!/\bname="(?:website|email)"/.test(tag)) continue;
- const aria = tag.match(/\baria-label="([^"]*)"/)?.[1] ?? "";
+ const nameMatch = tag.match(/\bname\s*=\s*(['"])(website|email)\1/i);
+ if (!nameMatch) continue;
+ const aria = tag.match(/\baria-label\s*=\s*(['"])(.*?)\1/i)?.[2] ?? "";🤖 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 1541 - 1547, Update the intake input
validation loop in the site-check logic to parse HTML attributes with flexible
whitespace and either single or double quotes, so both name and aria-label
values are recognized. Track matching fields per page and add failures when the
expected website and email inputs are absent, while preserving the existing
requirement for non-empty programmatic aria-labels.
There was a problem hiding this comment.
nish3451 has reached the 50-credit limit for trial accounts. To continue receiving code reviews, upgrade your plan.
There was a problem hiding this comment.
nish3451 has reached the 50-credit limit for trial accounts. To continue receiving code reviews, upgrade your plan.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 151cd77949
ℹ️ 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".
| 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.
Require each intake field before checking its label
If the email input is deleted or renamed, this continue leaves the page with zero matching email fields and records no failure, even though signupResponse rejects submissions without body.email (src/worker.js:352-359). I verified that deleting both email inputs still lets node scripts/check-site.mjs pass, so the new guard cannot prevent a regression that breaks the appraisal intake; assert that each page contains exactly one website and one email field before validating their labels.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
nish3451 has reached the 50-credit limit for trial accounts. To continue receiving code reviews, upgrade your plan.
There was a problem hiding this comment.
nish3451 has reached the 50-credit limit for trial accounts. To continue receiving code reviews, upgrade your plan.
There was a problem hiding this comment.
nish3451 has reached the 50-credit limit for trial accounts. To continue receiving code reviews, upgrade your plan.
There was a problem hiding this comment.
nish3451 has reached the 50-credit limit for trial accounts. To continue receiving code reviews, upgrade your plan.
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
There was a problem hiding this comment.
nish3451 has reached the 50-credit limit for trial accounts. To continue receiving code reviews, upgrade your plan.
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
There was a problem hiding this comment.
nish3451 has reached the 50-credit limit for trial accounts. To continue receiving code reviews, upgrade your plan.
There was a problem hiding this comment.
nish3451 has reached the 50-credit limit for trial accounts. To continue receiving code reviews, upgrade your plan.
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
What
Self-directed live walk (tier 1–2: public-promise gaps and UX breakage) found two fresh, uncovered defects on the served product — both confirmed live at 390×844 and 1280px on 2026-08-10, both byte-identical on
origin/main, both absent from every open PR's diff.1. Intake fields had no persistent programmatic labels (homepage + /audit).
Both
form.leadintakes labelled their website and email inputs only withplaceholdertext, which disappears the moment a buyer starts typing and isnot a programmatic label. Live DOM:
aria=null,hasLabel=falseon all fourinputs. Both pages now ship a stable
aria-labelon each input (placeholdersstay as visual hints).
2. Two document titles still branded the site "The Tiny Studio".
/pricingservedPricing & terms — The Tiny Studioand/brief-requestedserved
Request received — The Tiny Studio— the spaced name the site's ownidentity copy disavows (it collides with "The Tiny Studio LA" and other
unrelated businesses), while every other page said
TinyStudio. The pricing<title>also contradicted its ownog:title(TinyStudio — Pricing & terms).Both titles now name the brand; pricing's title matches its og:title exactly.
Deterministic guards (fail on
origin/main, pass here):scripts/check-site.mjsnow asserts all six served appraisal pages'document titles name
TinyStudioand never containThe Tiny Studio(the retired
/agent-deskpage is deliberately excluded: its title framesitself as retired and it is noindex).
scripts/check-site.mjsnow rejects anywebsite/emailintake input onthe homepage or /audit that lacks a non-empty
aria-label.Files
public/index.html— aria-label on website + email inputspublic/audit.html— aria-label on website + email inputspublic/pricing.html— title →TinyStudio — Pricing & termspublic/brief-requested.html— title →Request received — TinyStudioscripts/check-site.mjs— the two regression guards aboveVerification
npm testgreen: check + headings 6/6 + sitemap 7/7 + worker 53/53 + ui 16/16npm run check:render-blocking— all six pages PASS under production CSPnpx wrangler deploy --dry-run— passes (after removing a 0-byte/home/nish/package.jsonenvironment artifact that broke esbuild's upwardpackage.json lookup on this box; traced to backlog-console/actions.log)
errors (only the known
/brief-requestedplaceholder gtag CSP error,already owned by PR fix(worker): make the Google Ads conversion tag env-driven instead of a dead placeholder #52)
intended-outcome: no served appraisal page can brand itself "The Tiny Studio" in its document title again, and no appraisal intake field can lose its programmatic label when placeholder text disappears.
verify: npm run check
Summary by CodeRabbit
Accessibility
Updates
Quality Improvements