Skip to content

fix(public): disambiguate Tiny Studio from unrelated tiny studio brands - #29

Merged
nish3451 merged 1 commit into
mainfrom
fix/public-brand-disambiguation
Aug 9, 2026
Merged

fix(public): disambiguate Tiny Studio from unrelated tiny studio brands#29
nish3451 merged 1 commit into
mainfrom
fix/public-brand-disambiguation

Conversation

@nish3451

@nish3451 nish3451 commented Aug 9, 2026

Copy link
Copy Markdown
Collaborator

Closes the AI-answer confusion where Google AI answers conflate Tiny Studio / tinystudio.in with unrelated apps and studios that share the name.

What changed

  • public/index.html
    • Visible hero copy (human-first, not hidden): Tiny Studio is an independent product company at tinystudio.in, not affiliated with any other app or studio using the name Tiny Studio.
    • Organization JSON-LD hardened for entity disambiguation: alternateName: tinystudio.in and a description naming the unique qualifiers (tinystudio.in, Promptly, Drishti, 0509) plus the non-affiliation statement.
  • scripts/test-public-brand-disambiguation.mjs (new): asserts the visible statement and the Organization entity fields, wired into npm test and npm run ci.
  • package.json: test wiring only.

Why this shape

Follows the repo's own ai-search-audit-workflow no-hack rules: plain, crawlable, truthful copy that answers the confusion for a human first, plus structured data that already fits the content. No AI-only pages, hidden text, or keyword stuffing. The homepage is the entity-defining page; other public pages reference the same stable #organization id.

Validation

  • npm run ci: exit 0, all suites pass (new test: 11 checks, 0 failures)
  • git diff --check: clean

Summary by CodeRabbit

  • New Features

    • Added clearer homepage branding identifying Tiny Studio as an independent company.
    • Added messaging clarifying that Tiny Studio is not affiliated with similarly named apps or studios.
    • Enhanced Organization structured data with an alternate name and company description.
  • Tests

    • Added automated checks to verify homepage branding, structured data, and non-affiliation messaging.
    • Integrated these checks into standard testing and continuous integration.

Google AI answers conflate tinystudio.in with unrelated apps and studios
named Tiny Studio. The homepage now states plainly, in visible copy and in
the Organization structured data, that Tiny Studio is the independent
product company at tinystudio.in behind Promptly, Drishti, and 0509 and is
not affiliated with any other app or studio using the name. Adds a public
brand disambiguation test wired into npm test and npm run ci.

@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 9, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The homepage now includes Tiny Studio identity and non-affiliation messaging in visible content and Organization structured data. A new Node.js test validates these details and runs through both npm test and CI.

Changes

Brand disambiguation

Layer / File(s) Summary
Homepage identity metadata and messaging
public/index.html
The Organization JSON-LD and hero content identify Tiny Studio as an independent product company at tinystudio.in and state its non-affiliation with similarly named brands.
Automated brand validation
scripts/test-public-brand-disambiguation.mjs, package.json
The new test validates homepage text, Organization metadata, malformed JSON-LD handling, and npm script wiring. The test runs under both npm test and CI.

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: disambiguating Tiny Studio from unrelated brands.
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/public-brand-disambiguation

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

@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

🧹 Nitpick comments (1)
scripts/test-public-brand-disambiguation.mjs (1)

20-23: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Make JSON-LD extraction independent of attribute order.

Lines 20-23 only match a script tag whose type attribute is first, uses double quotes, and has no whitespace around =. A harmless markup change can make orgNode return null even when the Organization node is present. Match the type attribute independently of its position and quote style.

Proposed fix
 const jsonLdBlocksOf = (html) =>
-  [...html.matchAll(/<script\s+type="application\/ld\+json"[^>]*>([\s\S]*?)<\/script>/gi)].map(
-    (m) => m[1]
+  [...html.matchAll(
+    /<script\b[^>]*\btype\s*=\s*(['"])application\/ld\+json\1[^>]*>([\s\S]*?)<\/script>/gi
+  )].map(
+    (m) => m[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/test-public-brand-disambiguation.mjs` around lines 20 - 23, Update
jsonLdBlocksOf to recognize JSON-LD script tags regardless of attribute order,
single or double quotes around the type value, and whitespace around the equals
sign. Preserve extraction of the script contents while matching
type="application/ld+json" independently of neighboring attributes.
🤖 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/test-public-brand-disambiguation.mjs`:
- Around line 39-46: Update bodyText and the related assertion to inspect only
the rendered hero paragraph, excluding content inside template elements, hidden
elements, and inline CSS-hidden elements. Prefer selecting the intended hero
paragraph directly and extracting its visible text, while preserving the
existing normalization used for assertions.
- Around line 68-83: Normalize org.description once after the initial type
assertion, using the established string type guard and an empty-string fallback
for non-string values. Update the subsequent product-name and affiliation
assertions to call .includes() on that normalized string, while preserving their
existing required-content checks.

---

Nitpick comments:
In `@scripts/test-public-brand-disambiguation.mjs`:
- Around line 20-23: Update jsonLdBlocksOf to recognize JSON-LD script tags
regardless of attribute order, single or double quotes around the type value,
and whitespace around the equals sign. Preserve extraction of the script
contents while matching type="application/ld+json" independently of neighboring
attributes.
🪄 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: 9122dae1-055b-4ab2-ab6a-bf022fe44e2b

📥 Commits

Reviewing files that changed from the base of the PR and between ffe6e1f and 3de4059.

📒 Files selected for processing (3)
  • package.json
  • public/index.html
  • scripts/test-public-brand-disambiguation.mjs

Comment on lines +39 to +46
// Strip markup so assertions run against the visible, human-readable text.
const bodyText = (html) =>
html
.replace(/<script\b[\s\S]*?<\/script>/gi, " ")
.replace(/<style\b[\s\S]*?<\/style>/gi, " ")
.replace(/<[^>]+>/g, " ")
.replace(/\s+/g, " ")
.trim()

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

Limit the text assertion to rendered content.

bodyText removes tags, but it keeps text inside <template>, hidden elements, and elements hidden with inline CSS. A future change could move the non-affiliation copy out of the visible hero while this test still passes. Scope the assertion to the intended hero paragraph or use a parser that excludes non-rendered content.

🤖 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/test-public-brand-disambiguation.mjs` around lines 39 - 46, Update
bodyText and the related assertion to inspect only the rendered hero paragraph,
excluding content inside template elements, hidden elements, and inline
CSS-hidden elements. Prefer selecting the intended hero paragraph directly and
extracting its visible text, while preserving the existing normalization used
for assertions.

Comment on lines +68 to +83
ok(
typeof org.description === "string" && org.description.length > 0,
"organization carries a description"
)
ok(
org.description &&
org.description.includes("tinystudio.in") &&
org.description.includes("Promptly") &&
org.description.includes("Drishti") &&
org.description.includes("0509"),
"organization description names the unique products and home so the entity cannot be mistaken for another tiny studio"
)
ok(
org.description && org.description.includes("not affiliated"),
"organization description states it is not affiliated with other tiny studio brands"
)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

Reuse the description type guard before calling .includes().

The check at Lines 68-70 does not stop execution. If org.description is a truthy non-string value, Lines 72-78 and 80-82 throw TypeError. Normalize the description once, then use the normalized string for all assertions.

Proposed fix
 if (org) {
+  const description = typeof org.description === "string" ? org.description : ""
   ok(org.name === "Tiny Studio", "organization name is Tiny Studio")
   ok(org.alternateName === "tinystudio.in", "organization alternateName is tinystudio.in")
   ok(org.url === "https://tinystudio.in/", "organization url is the tinystudio.in home")
   ok(
-    typeof org.description === "string" && org.description.length > 0,
+    description.length > 0,
     "organization carries a description"
   )
   ok(
-    org.description &&
-      org.description.includes("tinystudio.in") &&
-      org.description.includes("Promptly") &&
-      org.description.includes("Drishti") &&
-      org.description.includes("0509"),
+    description.includes("tinystudio.in") &&
+      description.includes("Promptly") &&
+      description.includes("Drishti") &&
+      description.includes("0509"),
     "organization description names the unique products and home so the entity cannot be mistaken for another tiny studio"
   )
   ok(
-    org.description && org.description.includes("not affiliated"),
+    description.includes("not affiliated"),
     "organization description states it is not affiliated with other tiny studio brands"
   )
 }
📝 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
ok(
typeof org.description === "string" && org.description.length > 0,
"organization carries a description"
)
ok(
org.description &&
org.description.includes("tinystudio.in") &&
org.description.includes("Promptly") &&
org.description.includes("Drishti") &&
org.description.includes("0509"),
"organization description names the unique products and home so the entity cannot be mistaken for another tiny studio"
)
ok(
org.description && org.description.includes("not affiliated"),
"organization description states it is not affiliated with other tiny studio brands"
)
const description = typeof org.description === "string" ? org.description : ""
ok(
description.length > 0,
"organization carries a description"
)
ok(
description.includes("tinystudio.in") &&
description.includes("Promptly") &&
description.includes("Drishti") &&
description.includes("0509"),
"organization description names the unique products and home so the entity cannot be mistaken for another tiny studio"
)
ok(
description.includes("not affiliated"),
"organization description states it is not affiliated with other tiny studio brands"
)
🤖 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/test-public-brand-disambiguation.mjs` around lines 68 - 83, Normalize
org.description once after the initial type assertion, using the established
string type guard and an empty-string fallback for non-string values. Update the
subsequent product-name and affiliation assertions to call .includes() on that
normalized string, while preserving their existing required-content checks.

@nish3451
nish3451 merged commit 4202d54 into main Aug 9, 2026
3 checks passed
nish3451 added a commit that referenced this pull request Aug 11, 2026
… leave the June-20 bundle (#81)

* fix(public): add the tinystudio.in release lane (Cloudflare Pages deploy path repair)

The live site has served the 2026-06-20 bundle (07acd07) since June 20 while
17+ public PRs merged to main; the Cloudflare Pages git connection for
tiny-studio-3f5 never shows checks/statuses on commits and no deploy
workflow or secrets exist in the repo. The fleet Workers token lacks
Cloudflare Pages:Edit, so no automation on this box can publish today.

Add an in-repo release lane that works the moment a Pages-scoped token is
provisioned (documented fail-closed message):
- scripts/prepare-public-deploy-bundle.mjs: filtered bundle (public/ minus
  the snoozed-by-Nish managed-service buyer path from PRs #10/#11; every
  other merged fix preserved), fail-closed in both directions
- scripts/test-public-deploy-bundle.mjs: regression guard, wired into
  npm test/ci (62 checks)
- scripts/publish-public-site.mjs: prepare -> wrangler pages deploy to
  tiny-studio-3f5 -> live verification
- scripts/check-public-live-deploy.mjs: live proof for the deploy-path
  accept (H2-after-H1 /promptly/support/ #18/#20, JSON-LD /contact/ #19,
  real 404s #34, homepage portfolio-only #29 + no buyer path)
- .github/workflows/deploy-public-site.yml: vps-verify lane on push to main
- wrangler 4.120.0 devDependency

verify: npm test (603 checks, 0 failures); node scripts/prepare-public-deploy-bundle.mjs; git diff --check

* fix(public): attach the source commit to Cloudflare Pages deployments

wrangler pages deploy accepts --commit-hash/--commit-message/--commit-dirty
for dashboard provenance. The bundle already records source_commit in
deploy-manifest.json; pass it through so the Pages dashboard links the
deployment to the exact tinystudio-in commit that produced the bundle.

verify: node --check scripts/publish-public-site.mjs; node scripts/test-public-deploy-bundle.mjs (62 checks, 0 failures)

Co-authored-by: CommandCodeBot <noreply@commandcode.ai>

---------

Co-authored-by: CommandCodeBot <noreply@commandcode.ai>
nish3451 added a commit that referenced this pull request Aug 13, 2026
Source each URL's lastmod from the last git commit on main that touched
its HTML:
- / -> 4202d54 (#29) 2026-08-09
- privacy, terms, drishti/privacy -> 62a5dfe 2026-08-11
- all other pages -> a0d1de5 (#35) 2026-08-10
Fixes 5 stale 2026-05-20 dates and adds the 7 missing lastmod entries.
nish3451 added a commit that referenced this pull request Aug 15, 2026
…ource fixed in PR #29, live blocked on missing Cloudflare token (#182) (#184)

The Google AI answers disambiguation item is already fixed on main:
commit 4202d54 (PR #29) put the "independent product company at
tinystudio.in, not affiliated with other apps or studios using the
name" statement in every public page's Organization JSON-LD, in the
homepage visible copy, in llms.txt, and in its generator template, and
wired scripts/test-public-brand-disambiguation.mjs into npm test and
npm run ci. Re-verified against fresh origin/main: the guard script
passes (11 checks, 0 failures) and the source homepage carries the
identity statement. Live tinystudio.in still serves a stale bundle with
no JSON-LD and no disambiguation copy, and check-public-live-deploy.mjs
fails 7/15 checks; the deploy lane is fail-closed on the missing
CLOUDFLARE_API_TOKEN secret (NEEDS-NISH). No source change is possible
or needed; this report documents the verification.

Co-authored-by: CommandCodeBot <noreply@commandcode.ai>
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