Skip to content

feat(tangle-cloud): Show a visit-site link for every blueprint from website metadata#3267

Merged
drewstone merged 1 commit into
developfrom
feat/blueprint-website-link
Jun 15, 2026
Merged

feat(tangle-cloud): Show a visit-site link for every blueprint from website metadata#3267
drewstone merged 1 commit into
developfrom
feat/blueprint-website-link

Conversation

@drewstone

Copy link
Copy Markdown
Contributor

Lets any blueprint dev — iframe tier or not — link to their own dedicated site by setting website in metadata, and the cloud presents it. (Companion to #3266, which makes Surplus an iframe app.)

The gap

website already flows end-to-end: on-chain BlueprintMetadata.website + off-chain metadata JSON (website/homepage) → ParsedBlueprintMetadata.websiteBlueprint.websiteUrl, and the create/manage pages already author it. It renders on the legacy detail pages but not on the modern blueprint-app surfaces — so today a dev can publish a site URL that the new UI silently ignores. Render gap, no schema change.

Changes

  • BlueprintHostCard (declarative tier — the surface non-iframe blueprints get): render a "Visit site ↗" link when blueprint.websiteUrl is set, distinct from the publisher console (externalApp).
  • IframeBlueprintLayout (iframe tier): thread websiteUrl through and render the link in the top-nav slot beside Details — the per-blueprint navbar.
  • BlueprintAppLandingPage: pass canonicalBlueprint.websiteUrl into the layout.

Result

An external dev sets website in metadata → the cloud shows a direct link to their site, no iframe tier required (the explicit ask). First-party/iframe blueprints get it in the navbar too.

Not verified locally (monorepo typecheck needs a full worktree install); relies on CI + review. Coordinate with the in-flight feat/tangle-cloud-unified-shell work.

🤖 Generated with Claude Code

…om `website` metadata

The blueprint `website` field already flows end-to-end (on-chain BlueprintMetadata
+ off-chain metadata JSON -> ParsedBlueprintMetadata.website -> Blueprint.websiteUrl)
and renders on the legacy detail pages — but NOT on the modern blueprint-app
surfaces. So a dev (with or without the iframe tier) can publish their site URL,
yet the cloud never shows it on the new pages. This closes that render gap; no
schema change.

- BlueprintHostCard (declarative tier — the surface NON-iframe blueprints get):
  render a "Visit site ↗" link whenever blueprint.websiteUrl is set, distinct
  from the publisher console (externalApp).
- IframeBlueprintLayout (iframe tier): thread websiteUrl through and render the
  link in the top-nav slot next to Details — the per-blueprint navbar.
- BlueprintAppLandingPage: pass canonicalBlueprint.websiteUrl into the layout.

Any external blueprint dev now just sets `website` in their metadata and the
cloud presents a direct link to their own site, no iframe tier required.

NOT verified locally (monorepo typecheck needs a full worktree install); relies
on CI + review.
@drewstone drewstone requested a review from AtelyPham as a code owner June 15, 2026 00:27

@tangletools tangletools left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

✅ Auto-approved PR — e98752c1

Blanket team auto-approval is enabled for this reviewer service.
The full PR reviewer audit still runs separately and will publish findings if it detects issues.

tangletools · auto-approval · reason: blanket_auto_approve · 2026-06-15T00:27:56Z

@tangletools tangletools left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟢 Value Audit — sound

Verdict sound
Concerns 0 (none)
Heuristic 0.0s
Duplication 0.0s
Interrogation 30.0s (2 bridge agents)
Total 30.0s

No concerns — sound change, no better or existing approach found. ✅


What this audit checks

It judges the change on its merits — not whether it was tasked out in an issue. Unticketed, fast-moving work is fine; the question is whether the change is good and whether a better or existing approach should be used instead.

Pass What it asks
Heuristic Vague title? Whitespace-only or cruft-bearing diff? (content signals only)
Duplication Do added function/class names already exist elsewhere in the repo?
Value Audit What does it do? What goal does it achieve? Is it good? Better architecture or already-exists?
Usefulness Audit Does it integrate and fit? Will it hold up in real use and actually get used?

Findings are concerns, not blocks — the human reviewer decides what to do with them.

value-audit · 20260615T003032Z

@tangletools

Copy link
Copy Markdown
Contributor

✅ No Blockers — e98752c1

Readiness 69/100 · Confidence 65/100 · 4 findings (2 medium, 2 low)

deepseek: Correctness 69 · Security 69 · Testing 69 · Architecture 69

Full multi-shot audit completed 1/1 planned shots over 3 changed files. Global verifier still owns final merge decision.

🟠 MEDIUM websiteUrl allows http:// (non-TLS) while externalAppUrl requires https:// — apps/tangle-cloud/src/blueprintApps/components/IframeBlueprintLayout.tsx

websiteUrl is sanitized via sanitizePublicUrl → isValidHttpUrl (authoring.ts:717), which accepts both http: and https:. The sibling externalAppUrl prop uses isValidHttpsUrl (authoring.ts:232) which is HTTPS-only. In a DApp where users approve wallet transactions, linking to unencrypted HTTP destinations from the 'Visit site' button (line 175) creates a downgrade attack surface. Same issue in BlueprintHostCard.tsx:277. Fix: either (a) use isValidHttpsUrl for websiteUrl in parseBlueprintMetadataDocument (authoring.ts:1149-1150) or (b) re-validate at the component boundary.

🟠 MEDIUM BlueprintHostCard trusts unvalidated websiteUrl from callers — no defense-in-depth — apps/tangle-cloud/src/components/blueprintApps/BlueprintHostCard.tsx

BlueprintHostCard renders blueprint.websiteUrl directly into href (line 277) without any component-level URL validation. While current callers (blueprints/[id]/page.tsx:146, services/[id]/page.tsx:571) use useBlueprintDetails which goes through sanitizePublicUrl, the separate Substrate data path (blueprintHelpers.ts:249, toPrimitiveBlueprint.ts:50 via useBlueprintDetails.ts:162) assigns metadata.website to websiteUrl with zero sanitization via optionalBytesToString. If BlueprintHostCard is ever reused with data from that path, javascript: URLs in on-chain metadata would render as executable links. Fix: add a URL protocol validatio

🟡 LOW Inconsistent external-link icon rendering — apps/tangle-cloud/src/blueprintApps/components/IframeBlueprintLayout.tsx

The new 'Visit site' button at line 174 uses a hardcoded '↗' HTML entity (line 186), while BlueprintHostCard.tsx:283 uses the icon component from @tangle-network/icons. The rest of the IframeBlueprintLayout's external links (e.g., the 'Open standalone' in DetailsPanel at line 434)

🟡 LOW "Visit site" link lacks aria-label for screen readers — apps/tangle-cloud/src/components/blueprintApps/BlueprintHostCard.tsx

The new external link at line 276-284 renders 'Visit site' text, but that label is generic — it doesn't convey which site or that it opens externally. The sibling publisher console uses a button with inline text. For accessibility, add aria-label='Visit blueprint website (opens in new tab)' or similar. IframeBlueprintLayout.tsx:174 uses a title attribute but also has no aria-label.


tangletools · 2026-06-15T00:33:41Z · trace

@drewstone drewstone merged commit 611f0e5 into develop Jun 15, 2026
8 of 10 checks passed
@drewstone drewstone deleted the feat/blueprint-website-link branch June 15, 2026 01:46
@drewstone drewstone changed the title feat(tangle-cloud): show a "Visit site" link for every blueprint from website metadata feat(tangle-cloud): Show a visit-site link for every blueprint from website metadata Jun 15, 2026
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.

2 participants