feat(sell): allow for the control of your storefront branding - #663

Merged
OisinKyne merged 13 commits into
mainfrom
feat/storefront-customize
Jul 1, 2026
Merged

feat(sell): allow for the control of your storefront branding #663
OisinKyne merged 13 commits into
mainfrom
feat/storefront-customize

Conversation

@HananINouman

@HananINoumanHananINouman commented Jun 23, 2026

Copy link
Copy Markdown
Contributor

Operators can set seller-wide storefront branding with obol sell info set, independent of individual ServiceOffers. The controller publishes displayName, tagline, and logoUrl in the /api/services.json catalog envelope, and the public storefront consumes that envelope for the header, hero copy, metadata, manifest icons, favicon behavior, and generated OG image.

Summary

Screenshot 2026-06-24 at 9 33 45 AM

What changed:

  • Adds seller-wide storefront branding fields: display name, tagline, and logo URL.
  • Moves branding into the public /api/services.json catalog envelope so the storefront has one catalog fetch for services plus seller profile data.
  • Adds obol sell info support for configuring seller branding without coupling it to any one ServiceOffer.
  • Updates the public Next storefront to use seller branding in the header, metadata, web manifest, favicon/icon selection, and Open Graph image generation.
  • Keeps the page hero title stable as Agent services while using the seller tagline for supporting copy.
  • Fixes relative custom logo paths in /opengraph-image by resolving them against the public request origin before passing them to ImageResponse.
  • Runs gofmt on the controller changes.

Why it matters:

  • Sellers can present a recognizable storefront without duplicating branding across ServiceOffers.
  • The public storefront reads a single catalog document for both services and branding, reducing fetch duplication and avoiding a separate public /api/storefront.json route.
  • Relative logo paths no longer produce a runtime OG image failure.
  • This is the first branding slice before broader customizable storefront work. The larger architecture proposal is tracked in Architecture proposal: customizable public storefront via A2UI-style surface contract #669.

Risk level: medium

The change touches CLI UX, controller-rendered public catalog data, and public storefront rendering/metadata. It should not alter x402 payment routing, settlement, pricing, or ServiceOffer route behavior.

Commit under test: b734ca0aae5c0b2e75124956df6b3cf3bb7a5328

Base branch: main

Head branch: feat/storefront-customize

Scope

  • Code
  • Charts / manifests
  • Flows / QA scripts
  • Docs / skills
  • Images / dependencies
  • Other

Validation

CI checks at the time this description was updated:

CheckStatusLink
gitleaksPassedhttps://github.com/ObolNetwork/obol-stack/actions/runs/28174505168/job/83447072531
lint-testPassedhttps://github.com/ObolNetwork/obol-stack/actions/runs/28174505186/job/83447072559
CRD generation up-to-datePassedhttps://github.com/ObolNetwork/obol-stack/actions/runs/28174505186/job/83447072546
CodeQL Analyze (actions)In progresshttps://github.com/ObolNetwork/obol-stack/actions/runs/28174501577/job/83447068320
CodeQL Analyze (go)In progresshttps://github.com/ObolNetwork/obol-stack/actions/runs/28174501577/job/83447068299
CodeQL Analyze (javascript-typescript)In progresshttps://github.com/ObolNetwork/obol-stack/actions/runs/28174501577/job/83447068295
CodeQL Analyze (python)In progresshttps://github.com/ObolNetwork/obol-stack/actions/runs/28174501577/job/83447068329

Local/unit checks:

go test ./cmd/obol ./internal/storefront ./internal/serviceoffercontroller -count=1
PASS

Storefront build:

cd web/public-storefront
npm ci
npm run build
PASS

Notes:

  • npm ci reported existing dependency audit findings: 1 moderate, 1 high.
  • next build passed. It emitted a workspace-root warning because a higher-level /Users/bussyjd/yarn.lock exists in this local environment.

Runtime spot check:

Mocked /api/services.json with logoUrl: "/custom.png"
GET /opengraph-image
HTTP 200

This validates the reviewed failure mode where ImageResponse previously rejected relative custom logo paths with Image source must be an absolute URL.

Integration tests:

Not run. This PR changes storefront branding/catalog rendering, not payment settlement or live chain flows.

Flow tests:

FlowNetworkQA machine labelWorktreeResultArtifacts
Not runN/AN/AN/AN/AN/A

Release smoke:

Not run.

Runtime / Security Notes

  • Public route posture should remain unchanged for internal services: frontend and eRPC stay restricted to hostnames: ["obol.stack"].
  • Public storefront branding is intentionally public metadata in the service catalog envelope.
  • The storefront renderer still uses known local React components; this PR does not add arbitrary HTML, remote component execution, or public write actions.
  • Custom logo handling now resolves relative URLs against the incoming request origin for generated OG images.

Live Chain Evidence

Not applicable. This PR does not register ERC-8004 identity, perform x402 purchases, or settle on-chain payments.

Review Notes

Known gaps:

  • Broader storefront customization is intentionally out of scope for this PR. Architecture discussion and validation checklist are in Architecture proposal: customizable public storefront via A2UI-style surface contract #669.
  • Existing dependency audit findings from npm ci are not introduced or fixed here.
  • Local signature verification reports the commit has a good SSH signature, but local Git cannot map it to a principal because /Users/bussyjd/.gitallowedsigners is not configured in this environment.

Follow-ups:

Reviewer focus:

  • CLI naming and operator UX: obol sell info set as the canonical branding command.
  • Catalog contract: whether embedding branding in /api/services.json is the right public compatibility boundary.
  • Storefront rendering: metadata, manifest, icon, and OG behavior with default, absolute custom, and relative custom logos.
  • Security posture: confirm this does not broaden public tunnel exposure beyond intended storefront/catalog metadata.

Let operators set display name, tagline, and logo via `obol sell storefront`
independent of ServiceOffers. Controller publishes /api/storefront.json; the
public storefront consumes it for header, metadata, OG image, and favicon.
Co-authored-by: Cursor <cursoragent@cursor.com>
HananINoumanand others added 5 commits June 23, 2026 22:23
Add a dedicated x402/obol-storefront-profile informer so controller
republishes storefront.json on branding changes. Wrap fetchStorefront/
fetchServices in React.cache(), use ProfileNamespace for profile reads,
and log marshal failures.
Co-authored-by: Cursor <cursoragent@cursor.com>
Always show "Agent services" as the page title; use profile tagline in the
hero and displayName in the custom header so seller name is not duplicated.
Co-authored-by: Cursor <cursoragent@cursor.com>
Move displayName, tagline, and logoUrl into the public catalog, remove the
separate storefront.json route, and configure branding via obol sell info.
Co-authored-by: Cursor <cursoragent@cursor.com>
feat(sell): embed seller branding in /api/services.json envelope
@HananINoumanHananINouman changed the title feat(sell): add storefront branding profile and /api/storefront.jsonfeat(sell): add storefront branding profileJun 25, 2026
@OisinKyneOisinKyne changed the title feat(sell): add storefront branding profilefeat(sell): allow for the control of your storefront branding Jul 1, 2026
@OisinKyne
OisinKyne enabled auto-merge (rebase) July 1, 2026 01:44
auto-merge was automatically disabled July 1, 2026 01:44

Rebase failed

@OisinKyne
OisinKyne merged commit 2b247ac into mainJul 1, 2026
9 checks passed
@OisinKyne
OisinKyne deleted the feat/storefront-customize branch July 1, 2026 01:45
Sign up for freeto 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.

3 participants

@HananINouman@OisinKyne@bussyjd
, 'i'); if (__m === '*' || __re.test(location.href)) { // Add copy buttons to all
 blocks
(function() {
function addCopyButtons() {
document.querySelectorAll('pre code').forEach(function(codeBlock) {
if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;
codeBlock.parentElement.setAttribute('data-copy-added', 'true');
var btn = document.createElement('button');
btn.textContent = 'Copy';
btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';
btn.onmouseover = function() { this.style.opacity = '1'; };
btn.onmouseout = function() { this.style.opacity = '0.7'; };
btn.onclick = function() {
navigator.clipboard.writeText(codeBlock.textContent).then(function() {
btn.textContent = 'Copied!';
setTimeout(function() { btn.textContent = 'Copy'; }, 1500);
});
};
codeBlock.parentElement.style.position = 'relative';
codeBlock.parentElement.appendChild(btn);
});
}
addCopyButtons();
// Re-run on dynamic content
var observer = new MutationObserver(addCopyButtons);
observer.observe(document.body, { childList: true, subtree: true });
})();
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

feat(sell): allow for the control of your storefront branding - #663

Merged
OisinKyne merged 13 commits into
mainfrom
feat/storefront-customize
Jul 1, 2026
Merged

feat(sell): allow for the control of your storefront branding #663
OisinKyne merged 13 commits into
mainfrom
feat/storefront-customize

Conversation

@HananINouman

@HananINoumanHananINouman commented Jun 23, 2026

Copy link
Copy Markdown
Contributor

Operators can set seller-wide storefront branding with obol sell info set, independent of individual ServiceOffers. The controller publishes displayName, tagline, and logoUrl in the /api/services.json catalog envelope, and the public storefront consumes that envelope for the header, hero copy, metadata, manifest icons, favicon behavior, and generated OG image.

Summary

Screenshot 2026-06-24 at 9 33 45 AM

What changed:

  • Adds seller-wide storefront branding fields: display name, tagline, and logo URL.
  • Moves branding into the public /api/services.json catalog envelope so the storefront has one catalog fetch for services plus seller profile data.
  • Adds obol sell info support for configuring seller branding without coupling it to any one ServiceOffer.
  • Updates the public Next storefront to use seller branding in the header, metadata, web manifest, favicon/icon selection, and Open Graph image generation.
  • Keeps the page hero title stable as Agent services while using the seller tagline for supporting copy.
  • Fixes relative custom logo paths in /opengraph-image by resolving them against the public request origin before passing them to ImageResponse.
  • Runs gofmt on the controller changes.

Why it matters:

  • Sellers can present a recognizable storefront without duplicating branding across ServiceOffers.
  • The public storefront reads a single catalog document for both services and branding, reducing fetch duplication and avoiding a separate public /api/storefront.json route.
  • Relative logo paths no longer produce a runtime OG image failure.
  • This is the first branding slice before broader customizable storefront work. The larger architecture proposal is tracked in Architecture proposal: customizable public storefront via A2UI-style surface contract #669.

Risk level: medium

The change touches CLI UX, controller-rendered public catalog data, and public storefront rendering/metadata. It should not alter x402 payment routing, settlement, pricing, or ServiceOffer route behavior.

Commit under test: b734ca0aae5c0b2e75124956df6b3cf3bb7a5328

Base branch: main

Head branch: feat/storefront-customize

Scope

  • Code
  • Charts / manifests
  • Flows / QA scripts
  • Docs / skills
  • Images / dependencies
  • Other

Validation

CI checks at the time this description was updated:

CheckStatusLink
gitleaksPassedhttps://github.com/ObolNetwork/obol-stack/actions/runs/28174505168/job/83447072531
lint-testPassedhttps://github.com/ObolNetwork/obol-stack/actions/runs/28174505186/job/83447072559
CRD generation up-to-datePassedhttps://github.com/ObolNetwork/obol-stack/actions/runs/28174505186/job/83447072546
CodeQL Analyze (actions)In progresshttps://github.com/ObolNetwork/obol-stack/actions/runs/28174501577/job/83447068320
CodeQL Analyze (go)In progresshttps://github.com/ObolNetwork/obol-stack/actions/runs/28174501577/job/83447068299
CodeQL Analyze (javascript-typescript)In progresshttps://github.com/ObolNetwork/obol-stack/actions/runs/28174501577/job/83447068295
CodeQL Analyze (python)In progresshttps://github.com/ObolNetwork/obol-stack/actions/runs/28174501577/job/83447068329

Local/unit checks:

go test ./cmd/obol ./internal/storefront ./internal/serviceoffercontroller -count=1
PASS

Storefront build:

cd web/public-storefront
npm ci
npm run build
PASS

Notes:

  • npm ci reported existing dependency audit findings: 1 moderate, 1 high.
  • next build passed. It emitted a workspace-root warning because a higher-level /Users/bussyjd/yarn.lock exists in this local environment.

Runtime spot check:

Mocked /api/services.json with logoUrl: "/custom.png"
GET /opengraph-image
HTTP 200

This validates the reviewed failure mode where ImageResponse previously rejected relative custom logo paths with Image source must be an absolute URL.

Integration tests:

Not run. This PR changes storefront branding/catalog rendering, not payment settlement or live chain flows.

Flow tests:

FlowNetworkQA machine labelWorktreeResultArtifacts
Not runN/AN/AN/AN/AN/A

Release smoke:

Not run.

Runtime / Security Notes

  • Public route posture should remain unchanged for internal services: frontend and eRPC stay restricted to hostnames: ["obol.stack"].
  • Public storefront branding is intentionally public metadata in the service catalog envelope.
  • The storefront renderer still uses known local React components; this PR does not add arbitrary HTML, remote component execution, or public write actions.
  • Custom logo handling now resolves relative URLs against the incoming request origin for generated OG images.

Live Chain Evidence

Not applicable. This PR does not register ERC-8004 identity, perform x402 purchases, or settle on-chain payments.

Review Notes

Known gaps:

  • Broader storefront customization is intentionally out of scope for this PR. Architecture discussion and validation checklist are in Architecture proposal: customizable public storefront via A2UI-style surface contract #669.
  • Existing dependency audit findings from npm ci are not introduced or fixed here.
  • Local signature verification reports the commit has a good SSH signature, but local Git cannot map it to a principal because /Users/bussyjd/.gitallowedsigners is not configured in this environment.

Follow-ups:

Reviewer focus:

  • CLI naming and operator UX: obol sell info set as the canonical branding command.
  • Catalog contract: whether embedding branding in /api/services.json is the right public compatibility boundary.
  • Storefront rendering: metadata, manifest, icon, and OG behavior with default, absolute custom, and relative custom logos.
  • Security posture: confirm this does not broaden public tunnel exposure beyond intended storefront/catalog metadata.

Let operators set display name, tagline, and logo via `obol sell storefront`
independent of ServiceOffers. Controller publishes /api/storefront.json; the
public storefront consumes it for header, metadata, OG image, and favicon.
Co-authored-by: Cursor <cursoragent@cursor.com>
HananINoumanand others added 5 commits June 23, 2026 22:23
Add a dedicated x402/obol-storefront-profile informer so controller
republishes storefront.json on branding changes. Wrap fetchStorefront/
fetchServices in React.cache(), use ProfileNamespace for profile reads,
and log marshal failures.
Co-authored-by: Cursor <cursoragent@cursor.com>
Always show "Agent services" as the page title; use profile tagline in the
hero and displayName in the custom header so seller name is not duplicated.
Co-authored-by: Cursor <cursoragent@cursor.com>
Move displayName, tagline, and logoUrl into the public catalog, remove the
separate storefront.json route, and configure branding via obol sell info.
Co-authored-by: Cursor <cursoragent@cursor.com>
feat(sell): embed seller branding in /api/services.json envelope
@HananINoumanHananINouman changed the title feat(sell): add storefront branding profile and /api/storefront.jsonfeat(sell): add storefront branding profileJun 25, 2026
@OisinKyneOisinKyne changed the title feat(sell): add storefront branding profilefeat(sell): allow for the control of your storefront branding Jul 1, 2026
@OisinKyne
OisinKyne enabled auto-merge (rebase) July 1, 2026 01:44
auto-merge was automatically disabled July 1, 2026 01:44

Rebase failed

@OisinKyne
OisinKyne merged commit 2b247ac into mainJul 1, 2026
9 checks passed
@OisinKyne
OisinKyne deleted the feat/storefront-customize branch July 1, 2026 01:45
Sign up for freeto 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.

3 participants

@HananINouman@OisinKyne@bussyjd
, 'i'); if (__m === '*' || __re.test(location.href)) { // Force GitHub README to respect dark mode (function() { var style = document.createElement('style'); style.textContent = ' .markdown-body { color-scheme: dark light; } .markdown-body pre { background: #161b22 !important; } .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; } .markdown-body table th, .markdown-body table td { border-color: #30363d !important; } .markdown-body img { background: #0d1117; } .markdown-body blockquote { border-left-color: #8b949e; } .markdown-body hr { border-color: #30363d; } '; document.head.appendChild(style); })(); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

feat(sell): allow for the control of your storefront branding - #663

Merged
OisinKyne merged 13 commits into
mainfrom
feat/storefront-customize
Jul 1, 2026
Merged

feat(sell): allow for the control of your storefront branding #663
OisinKyne merged 13 commits into
mainfrom
feat/storefront-customize

Conversation

@HananINouman

@HananINoumanHananINouman commented Jun 23, 2026

Copy link
Copy Markdown
Contributor

Operators can set seller-wide storefront branding with obol sell info set, independent of individual ServiceOffers. The controller publishes displayName, tagline, and logoUrl in the /api/services.json catalog envelope, and the public storefront consumes that envelope for the header, hero copy, metadata, manifest icons, favicon behavior, and generated OG image.

Summary

Screenshot 2026-06-24 at 9 33 45 AM

What changed:

  • Adds seller-wide storefront branding fields: display name, tagline, and logo URL.
  • Moves branding into the public /api/services.json catalog envelope so the storefront has one catalog fetch for services plus seller profile data.
  • Adds obol sell info support for configuring seller branding without coupling it to any one ServiceOffer.
  • Updates the public Next storefront to use seller branding in the header, metadata, web manifest, favicon/icon selection, and Open Graph image generation.
  • Keeps the page hero title stable as Agent services while using the seller tagline for supporting copy.
  • Fixes relative custom logo paths in /opengraph-image by resolving them against the public request origin before passing them to ImageResponse.
  • Runs gofmt on the controller changes.

Why it matters:

  • Sellers can present a recognizable storefront without duplicating branding across ServiceOffers.
  • The public storefront reads a single catalog document for both services and branding, reducing fetch duplication and avoiding a separate public /api/storefront.json route.
  • Relative logo paths no longer produce a runtime OG image failure.
  • This is the first branding slice before broader customizable storefront work. The larger architecture proposal is tracked in Architecture proposal: customizable public storefront via A2UI-style surface contract #669.

Risk level: medium

The change touches CLI UX, controller-rendered public catalog data, and public storefront rendering/metadata. It should not alter x402 payment routing, settlement, pricing, or ServiceOffer route behavior.

Commit under test: b734ca0aae5c0b2e75124956df6b3cf3bb7a5328

Base branch: main

Head branch: feat/storefront-customize

Scope

  • Code
  • Charts / manifests
  • Flows / QA scripts
  • Docs / skills
  • Images / dependencies
  • Other

Validation

CI checks at the time this description was updated:

CheckStatusLink
gitleaksPassedhttps://github.com/ObolNetwork/obol-stack/actions/runs/28174505168/job/83447072531
lint-testPassedhttps://github.com/ObolNetwork/obol-stack/actions/runs/28174505186/job/83447072559
CRD generation up-to-datePassedhttps://github.com/ObolNetwork/obol-stack/actions/runs/28174505186/job/83447072546
CodeQL Analyze (actions)In progresshttps://github.com/ObolNetwork/obol-stack/actions/runs/28174501577/job/83447068320
CodeQL Analyze (go)In progresshttps://github.com/ObolNetwork/obol-stack/actions/runs/28174501577/job/83447068299
CodeQL Analyze (javascript-typescript)In progresshttps://github.com/ObolNetwork/obol-stack/actions/runs/28174501577/job/83447068295
CodeQL Analyze (python)In progresshttps://github.com/ObolNetwork/obol-stack/actions/runs/28174501577/job/83447068329

Local/unit checks:

go test ./cmd/obol ./internal/storefront ./internal/serviceoffercontroller -count=1
PASS

Storefront build:

cd web/public-storefront
npm ci
npm run build
PASS

Notes:

  • npm ci reported existing dependency audit findings: 1 moderate, 1 high.
  • next build passed. It emitted a workspace-root warning because a higher-level /Users/bussyjd/yarn.lock exists in this local environment.

Runtime spot check:

Mocked /api/services.json with logoUrl: "/custom.png"
GET /opengraph-image
HTTP 200

This validates the reviewed failure mode where ImageResponse previously rejected relative custom logo paths with Image source must be an absolute URL.

Integration tests:

Not run. This PR changes storefront branding/catalog rendering, not payment settlement or live chain flows.

Flow tests:

FlowNetworkQA machine labelWorktreeResultArtifacts
Not runN/AN/AN/AN/AN/A

Release smoke:

Not run.

Runtime / Security Notes

  • Public route posture should remain unchanged for internal services: frontend and eRPC stay restricted to hostnames: ["obol.stack"].
  • Public storefront branding is intentionally public metadata in the service catalog envelope.
  • The storefront renderer still uses known local React components; this PR does not add arbitrary HTML, remote component execution, or public write actions.
  • Custom logo handling now resolves relative URLs against the incoming request origin for generated OG images.

Live Chain Evidence

Not applicable. This PR does not register ERC-8004 identity, perform x402 purchases, or settle on-chain payments.

Review Notes

Known gaps:

  • Broader storefront customization is intentionally out of scope for this PR. Architecture discussion and validation checklist are in Architecture proposal: customizable public storefront via A2UI-style surface contract #669.
  • Existing dependency audit findings from npm ci are not introduced or fixed here.
  • Local signature verification reports the commit has a good SSH signature, but local Git cannot map it to a principal because /Users/bussyjd/.gitallowedsigners is not configured in this environment.

Follow-ups:

Reviewer focus:

  • CLI naming and operator UX: obol sell info set as the canonical branding command.
  • Catalog contract: whether embedding branding in /api/services.json is the right public compatibility boundary.
  • Storefront rendering: metadata, manifest, icon, and OG behavior with default, absolute custom, and relative custom logos.
  • Security posture: confirm this does not broaden public tunnel exposure beyond intended storefront/catalog metadata.

Let operators set display name, tagline, and logo via `obol sell storefront`
independent of ServiceOffers. Controller publishes /api/storefront.json; the
public storefront consumes it for header, metadata, OG image, and favicon.
Co-authored-by: Cursor <cursoragent@cursor.com>
HananINoumanand others added 5 commits June 23, 2026 22:23
Add a dedicated x402/obol-storefront-profile informer so controller
republishes storefront.json on branding changes. Wrap fetchStorefront/
fetchServices in React.cache(), use ProfileNamespace for profile reads,
and log marshal failures.
Co-authored-by: Cursor <cursoragent@cursor.com>
Always show "Agent services" as the page title; use profile tagline in the
hero and displayName in the custom header so seller name is not duplicated.
Co-authored-by: Cursor <cursoragent@cursor.com>
Move displayName, tagline, and logoUrl into the public catalog, remove the
separate storefront.json route, and configure branding via obol sell info.
Co-authored-by: Cursor <cursoragent@cursor.com>
feat(sell): embed seller branding in /api/services.json envelope
@HananINoumanHananINouman changed the title feat(sell): add storefront branding profile and /api/storefront.jsonfeat(sell): add storefront branding profileJun 25, 2026
@OisinKyneOisinKyne changed the title feat(sell): add storefront branding profilefeat(sell): allow for the control of your storefront branding Jul 1, 2026
@OisinKyne
OisinKyne enabled auto-merge (rebase) July 1, 2026 01:44
auto-merge was automatically disabled July 1, 2026 01:44

Rebase failed

@OisinKyne
OisinKyne merged commit 2b247ac into mainJul 1, 2026
9 checks passed
@OisinKyne
OisinKyne deleted the feat/storefront-customize branch July 1, 2026 01:45
Sign up for freeto 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.

3 participants

@HananINouman@OisinKyne@bussyjd
, 'i'); if (__m === '*' || __re.test(location.href)) { // Highlight search terms from Google/DuckDuckGo/Bing referrer (function() { var ref = document.referrer; var terms = []; if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) { var url = new URL(ref); var q = url.searchParams.get('q') || url.searchParams.get('p'); if (q) { terms = q.split(/\s+/).filter(function(t) { return t.length > 2; }); } } if (terms.length === 0) return; var style = document.createElement('style'); style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }'; document.head.appendChild(style); function highlight(node) { if (node.nodeType === 3) { // text node var text = node.textContent; var found = false; terms.forEach(function(term) { var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\]\\]/g, '\\') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

feat(sell): allow for the control of your storefront branding - #663

Merged
OisinKyne merged 13 commits into
mainfrom
feat/storefront-customize
Jul 1, 2026
Merged

feat(sell): allow for the control of your storefront branding #663
OisinKyne merged 13 commits into
mainfrom
feat/storefront-customize

Conversation

@HananINouman

@HananINoumanHananINouman commented Jun 23, 2026

Copy link
Copy Markdown
Contributor

Operators can set seller-wide storefront branding with obol sell info set, independent of individual ServiceOffers. The controller publishes displayName, tagline, and logoUrl in the /api/services.json catalog envelope, and the public storefront consumes that envelope for the header, hero copy, metadata, manifest icons, favicon behavior, and generated OG image.

Summary

Screenshot 2026-06-24 at 9 33 45 AM

What changed:

  • Adds seller-wide storefront branding fields: display name, tagline, and logo URL.
  • Moves branding into the public /api/services.json catalog envelope so the storefront has one catalog fetch for services plus seller profile data.
  • Adds obol sell info support for configuring seller branding without coupling it to any one ServiceOffer.
  • Updates the public Next storefront to use seller branding in the header, metadata, web manifest, favicon/icon selection, and Open Graph image generation.
  • Keeps the page hero title stable as Agent services while using the seller tagline for supporting copy.
  • Fixes relative custom logo paths in /opengraph-image by resolving them against the public request origin before passing them to ImageResponse.
  • Runs gofmt on the controller changes.

Why it matters:

  • Sellers can present a recognizable storefront without duplicating branding across ServiceOffers.
  • The public storefront reads a single catalog document for both services and branding, reducing fetch duplication and avoiding a separate public /api/storefront.json route.
  • Relative logo paths no longer produce a runtime OG image failure.
  • This is the first branding slice before broader customizable storefront work. The larger architecture proposal is tracked in Architecture proposal: customizable public storefront via A2UI-style surface contract #669.

Risk level: medium

The change touches CLI UX, controller-rendered public catalog data, and public storefront rendering/metadata. It should not alter x402 payment routing, settlement, pricing, or ServiceOffer route behavior.

Commit under test: b734ca0aae5c0b2e75124956df6b3cf3bb7a5328

Base branch: main

Head branch: feat/storefront-customize

Scope

  • Code
  • Charts / manifests
  • Flows / QA scripts
  • Docs / skills
  • Images / dependencies
  • Other

Validation

CI checks at the time this description was updated:

CheckStatusLink
gitleaksPassedhttps://github.com/ObolNetwork/obol-stack/actions/runs/28174505168/job/83447072531
lint-testPassedhttps://github.com/ObolNetwork/obol-stack/actions/runs/28174505186/job/83447072559
CRD generation up-to-datePassedhttps://github.com/ObolNetwork/obol-stack/actions/runs/28174505186/job/83447072546
CodeQL Analyze (actions)In progresshttps://github.com/ObolNetwork/obol-stack/actions/runs/28174501577/job/83447068320
CodeQL Analyze (go)In progresshttps://github.com/ObolNetwork/obol-stack/actions/runs/28174501577/job/83447068299
CodeQL Analyze (javascript-typescript)In progresshttps://github.com/ObolNetwork/obol-stack/actions/runs/28174501577/job/83447068295
CodeQL Analyze (python)In progresshttps://github.com/ObolNetwork/obol-stack/actions/runs/28174501577/job/83447068329

Local/unit checks:

go test ./cmd/obol ./internal/storefront ./internal/serviceoffercontroller -count=1
PASS

Storefront build:

cd web/public-storefront
npm ci
npm run build
PASS

Notes:

  • npm ci reported existing dependency audit findings: 1 moderate, 1 high.
  • next build passed. It emitted a workspace-root warning because a higher-level /Users/bussyjd/yarn.lock exists in this local environment.

Runtime spot check:

Mocked /api/services.json with logoUrl: "/custom.png"
GET /opengraph-image
HTTP 200

This validates the reviewed failure mode where ImageResponse previously rejected relative custom logo paths with Image source must be an absolute URL.

Integration tests:

Not run. This PR changes storefront branding/catalog rendering, not payment settlement or live chain flows.

Flow tests:

FlowNetworkQA machine labelWorktreeResultArtifacts
Not runN/AN/AN/AN/AN/A

Release smoke:

Not run.

Runtime / Security Notes

  • Public route posture should remain unchanged for internal services: frontend and eRPC stay restricted to hostnames: ["obol.stack"].
  • Public storefront branding is intentionally public metadata in the service catalog envelope.
  • The storefront renderer still uses known local React components; this PR does not add arbitrary HTML, remote component execution, or public write actions.
  • Custom logo handling now resolves relative URLs against the incoming request origin for generated OG images.

Live Chain Evidence

Not applicable. This PR does not register ERC-8004 identity, perform x402 purchases, or settle on-chain payments.

Review Notes

Known gaps:

  • Broader storefront customization is intentionally out of scope for this PR. Architecture discussion and validation checklist are in Architecture proposal: customizable public storefront via A2UI-style surface contract #669.
  • Existing dependency audit findings from npm ci are not introduced or fixed here.
  • Local signature verification reports the commit has a good SSH signature, but local Git cannot map it to a principal because /Users/bussyjd/.gitallowedsigners is not configured in this environment.

Follow-ups:

Reviewer focus:

  • CLI naming and operator UX: obol sell info set as the canonical branding command.
  • Catalog contract: whether embedding branding in /api/services.json is the right public compatibility boundary.
  • Storefront rendering: metadata, manifest, icon, and OG behavior with default, absolute custom, and relative custom logos.
  • Security posture: confirm this does not broaden public tunnel exposure beyond intended storefront/catalog metadata.

Let operators set display name, tagline, and logo via `obol sell storefront`
independent of ServiceOffers. Controller publishes /api/storefront.json; the
public storefront consumes it for header, metadata, OG image, and favicon.
Co-authored-by: Cursor <cursoragent@cursor.com>
HananINoumanand others added 5 commits June 23, 2026 22:23
Add a dedicated x402/obol-storefront-profile informer so controller
republishes storefront.json on branding changes. Wrap fetchStorefront/
fetchServices in React.cache(), use ProfileNamespace for profile reads,
and log marshal failures.
Co-authored-by: Cursor <cursoragent@cursor.com>
Always show "Agent services" as the page title; use profile tagline in the
hero and displayName in the custom header so seller name is not duplicated.
Co-authored-by: Cursor <cursoragent@cursor.com>
Move displayName, tagline, and logoUrl into the public catalog, remove the
separate storefront.json route, and configure branding via obol sell info.
Co-authored-by: Cursor <cursoragent@cursor.com>
feat(sell): embed seller branding in /api/services.json envelope
@HananINoumanHananINouman changed the title feat(sell): add storefront branding profile and /api/storefront.jsonfeat(sell): add storefront branding profileJun 25, 2026
@OisinKyneOisinKyne changed the title feat(sell): add storefront branding profilefeat(sell): allow for the control of your storefront branding Jul 1, 2026
@OisinKyne
OisinKyne enabled auto-merge (rebase) July 1, 2026 01:44
auto-merge was automatically disabled July 1, 2026 01:44

Rebase failed

@OisinKyne
OisinKyne merged commit 2b247ac into mainJul 1, 2026
9 checks passed
@OisinKyne
OisinKyne deleted the feat/storefront-customize branch July 1, 2026 01:45
Sign up for freeto 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.

3 participants

@HananINouman@OisinKyne@bussyjd
, 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

feat(sell): allow for the control of your storefront branding - #663

Merged
OisinKyne merged 13 commits into
mainfrom
feat/storefront-customize
Jul 1, 2026
Merged

feat(sell): allow for the control of your storefront branding #663
OisinKyne merged 13 commits into
mainfrom
feat/storefront-customize

Conversation

@HananINouman

@HananINoumanHananINouman commented Jun 23, 2026

Copy link
Copy Markdown
Contributor

Operators can set seller-wide storefront branding with obol sell info set, independent of individual ServiceOffers. The controller publishes displayName, tagline, and logoUrl in the /api/services.json catalog envelope, and the public storefront consumes that envelope for the header, hero copy, metadata, manifest icons, favicon behavior, and generated OG image.

Summary

Screenshot 2026-06-24 at 9 33 45 AM

What changed:

  • Adds seller-wide storefront branding fields: display name, tagline, and logo URL.
  • Moves branding into the public /api/services.json catalog envelope so the storefront has one catalog fetch for services plus seller profile data.
  • Adds obol sell info support for configuring seller branding without coupling it to any one ServiceOffer.
  • Updates the public Next storefront to use seller branding in the header, metadata, web manifest, favicon/icon selection, and Open Graph image generation.
  • Keeps the page hero title stable as Agent services while using the seller tagline for supporting copy.
  • Fixes relative custom logo paths in /opengraph-image by resolving them against the public request origin before passing them to ImageResponse.
  • Runs gofmt on the controller changes.

Why it matters:

  • Sellers can present a recognizable storefront without duplicating branding across ServiceOffers.
  • The public storefront reads a single catalog document for both services and branding, reducing fetch duplication and avoiding a separate public /api/storefront.json route.
  • Relative logo paths no longer produce a runtime OG image failure.
  • This is the first branding slice before broader customizable storefront work. The larger architecture proposal is tracked in Architecture proposal: customizable public storefront via A2UI-style surface contract #669.

Risk level: medium

The change touches CLI UX, controller-rendered public catalog data, and public storefront rendering/metadata. It should not alter x402 payment routing, settlement, pricing, or ServiceOffer route behavior.

Commit under test: b734ca0aae5c0b2e75124956df6b3cf3bb7a5328

Base branch: main

Head branch: feat/storefront-customize

Scope

  • Code
  • Charts / manifests
  • Flows / QA scripts
  • Docs / skills
  • Images / dependencies
  • Other

Validation

CI checks at the time this description was updated:

CheckStatusLink
gitleaksPassedhttps://github.com/ObolNetwork/obol-stack/actions/runs/28174505168/job/83447072531
lint-testPassedhttps://github.com/ObolNetwork/obol-stack/actions/runs/28174505186/job/83447072559
CRD generation up-to-datePassedhttps://github.com/ObolNetwork/obol-stack/actions/runs/28174505186/job/83447072546
CodeQL Analyze (actions)In progresshttps://github.com/ObolNetwork/obol-stack/actions/runs/28174501577/job/83447068320
CodeQL Analyze (go)In progresshttps://github.com/ObolNetwork/obol-stack/actions/runs/28174501577/job/83447068299
CodeQL Analyze (javascript-typescript)In progresshttps://github.com/ObolNetwork/obol-stack/actions/runs/28174501577/job/83447068295
CodeQL Analyze (python)In progresshttps://github.com/ObolNetwork/obol-stack/actions/runs/28174501577/job/83447068329

Local/unit checks:

go test ./cmd/obol ./internal/storefront ./internal/serviceoffercontroller -count=1
PASS

Storefront build:

cd web/public-storefront
npm ci
npm run build
PASS

Notes:

  • npm ci reported existing dependency audit findings: 1 moderate, 1 high.
  • next build passed. It emitted a workspace-root warning because a higher-level /Users/bussyjd/yarn.lock exists in this local environment.

Runtime spot check:

Mocked /api/services.json with logoUrl: "/custom.png"
GET /opengraph-image
HTTP 200

This validates the reviewed failure mode where ImageResponse previously rejected relative custom logo paths with Image source must be an absolute URL.

Integration tests:

Not run. This PR changes storefront branding/catalog rendering, not payment settlement or live chain flows.

Flow tests:

FlowNetworkQA machine labelWorktreeResultArtifacts
Not runN/AN/AN/AN/AN/A

Release smoke:

Not run.

Runtime / Security Notes

  • Public route posture should remain unchanged for internal services: frontend and eRPC stay restricted to hostnames: ["obol.stack"].
  • Public storefront branding is intentionally public metadata in the service catalog envelope.
  • The storefront renderer still uses known local React components; this PR does not add arbitrary HTML, remote component execution, or public write actions.
  • Custom logo handling now resolves relative URLs against the incoming request origin for generated OG images.

Live Chain Evidence

Not applicable. This PR does not register ERC-8004 identity, perform x402 purchases, or settle on-chain payments.

Review Notes

Known gaps:

  • Broader storefront customization is intentionally out of scope for this PR. Architecture discussion and validation checklist are in Architecture proposal: customizable public storefront via A2UI-style surface contract #669.
  • Existing dependency audit findings from npm ci are not introduced or fixed here.
  • Local signature verification reports the commit has a good SSH signature, but local Git cannot map it to a principal because /Users/bussyjd/.gitallowedsigners is not configured in this environment.

Follow-ups:

Reviewer focus:

  • CLI naming and operator UX: obol sell info set as the canonical branding command.
  • Catalog contract: whether embedding branding in /api/services.json is the right public compatibility boundary.
  • Storefront rendering: metadata, manifest, icon, and OG behavior with default, absolute custom, and relative custom logos.
  • Security posture: confirm this does not broaden public tunnel exposure beyond intended storefront/catalog metadata.

Let operators set display name, tagline, and logo via `obol sell storefront`
independent of ServiceOffers. Controller publishes /api/storefront.json; the
public storefront consumes it for header, metadata, OG image, and favicon.
Co-authored-by: Cursor <cursoragent@cursor.com>
HananINoumanand others added 5 commits June 23, 2026 22:23
Add a dedicated x402/obol-storefront-profile informer so controller
republishes storefront.json on branding changes. Wrap fetchStorefront/
fetchServices in React.cache(), use ProfileNamespace for profile reads,
and log marshal failures.
Co-authored-by: Cursor <cursoragent@cursor.com>
Always show "Agent services" as the page title; use profile tagline in the
hero and displayName in the custom header so seller name is not duplicated.
Co-authored-by: Cursor <cursoragent@cursor.com>
Move displayName, tagline, and logoUrl into the public catalog, remove the
separate storefront.json route, and configure branding via obol sell info.
Co-authored-by: Cursor <cursoragent@cursor.com>
feat(sell): embed seller branding in /api/services.json envelope
@HananINoumanHananINouman changed the title feat(sell): add storefront branding profile and /api/storefront.jsonfeat(sell): add storefront branding profileJun 25, 2026
@OisinKyneOisinKyne changed the title feat(sell): add storefront branding profilefeat(sell): allow for the control of your storefront branding Jul 1, 2026
@OisinKyne
OisinKyne enabled auto-merge (rebase) July 1, 2026 01:44
auto-merge was automatically disabled July 1, 2026 01:44

Rebase failed

@OisinKyne
OisinKyne merged commit 2b247ac into mainJul 1, 2026
9 checks passed
@OisinKyne
OisinKyne deleted the feat/storefront-customize branch July 1, 2026 01:45
Sign up for freeto 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.

3 participants

@HananINouman@OisinKyne@bussyjd
, 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

feat(sell): allow for the control of your storefront branding - #663

Merged
OisinKyne merged 13 commits into
mainfrom
feat/storefront-customize
Jul 1, 2026
Merged

feat(sell): allow for the control of your storefront branding #663
OisinKyne merged 13 commits into
mainfrom
feat/storefront-customize

Conversation

@HananINouman

@HananINoumanHananINouman commented Jun 23, 2026

Copy link
Copy Markdown
Contributor

Operators can set seller-wide storefront branding with obol sell info set, independent of individual ServiceOffers. The controller publishes displayName, tagline, and logoUrl in the /api/services.json catalog envelope, and the public storefront consumes that envelope for the header, hero copy, metadata, manifest icons, favicon behavior, and generated OG image.

Summary

Screenshot 2026-06-24 at 9 33 45 AM

What changed:

  • Adds seller-wide storefront branding fields: display name, tagline, and logo URL.
  • Moves branding into the public /api/services.json catalog envelope so the storefront has one catalog fetch for services plus seller profile data.
  • Adds obol sell info support for configuring seller branding without coupling it to any one ServiceOffer.
  • Updates the public Next storefront to use seller branding in the header, metadata, web manifest, favicon/icon selection, and Open Graph image generation.
  • Keeps the page hero title stable as Agent services while using the seller tagline for supporting copy.
  • Fixes relative custom logo paths in /opengraph-image by resolving them against the public request origin before passing them to ImageResponse.
  • Runs gofmt on the controller changes.

Why it matters:

  • Sellers can present a recognizable storefront without duplicating branding across ServiceOffers.
  • The public storefront reads a single catalog document for both services and branding, reducing fetch duplication and avoiding a separate public /api/storefront.json route.
  • Relative logo paths no longer produce a runtime OG image failure.
  • This is the first branding slice before broader customizable storefront work. The larger architecture proposal is tracked in Architecture proposal: customizable public storefront via A2UI-style surface contract #669.

Risk level: medium

The change touches CLI UX, controller-rendered public catalog data, and public storefront rendering/metadata. It should not alter x402 payment routing, settlement, pricing, or ServiceOffer route behavior.

Commit under test: b734ca0aae5c0b2e75124956df6b3cf3bb7a5328

Base branch: main

Head branch: feat/storefront-customize

Scope

  • Code
  • Charts / manifests
  • Flows / QA scripts
  • Docs / skills
  • Images / dependencies
  • Other

Validation

CI checks at the time this description was updated:

CheckStatusLink
gitleaksPassedhttps://github.com/ObolNetwork/obol-stack/actions/runs/28174505168/job/83447072531
lint-testPassedhttps://github.com/ObolNetwork/obol-stack/actions/runs/28174505186/job/83447072559
CRD generation up-to-datePassedhttps://github.com/ObolNetwork/obol-stack/actions/runs/28174505186/job/83447072546
CodeQL Analyze (actions)In progresshttps://github.com/ObolNetwork/obol-stack/actions/runs/28174501577/job/83447068320
CodeQL Analyze (go)In progresshttps://github.com/ObolNetwork/obol-stack/actions/runs/28174501577/job/83447068299
CodeQL Analyze (javascript-typescript)In progresshttps://github.com/ObolNetwork/obol-stack/actions/runs/28174501577/job/83447068295
CodeQL Analyze (python)In progresshttps://github.com/ObolNetwork/obol-stack/actions/runs/28174501577/job/83447068329

Local/unit checks:

go test ./cmd/obol ./internal/storefront ./internal/serviceoffercontroller -count=1
PASS

Storefront build:

cd web/public-storefront
npm ci
npm run build
PASS

Notes:

  • npm ci reported existing dependency audit findings: 1 moderate, 1 high.
  • next build passed. It emitted a workspace-root warning because a higher-level /Users/bussyjd/yarn.lock exists in this local environment.

Runtime spot check:

Mocked /api/services.json with logoUrl: "/custom.png"
GET /opengraph-image
HTTP 200

This validates the reviewed failure mode where ImageResponse previously rejected relative custom logo paths with Image source must be an absolute URL.

Integration tests:

Not run. This PR changes storefront branding/catalog rendering, not payment settlement or live chain flows.

Flow tests:

FlowNetworkQA machine labelWorktreeResultArtifacts
Not runN/AN/AN/AN/AN/A

Release smoke:

Not run.

Runtime / Security Notes

  • Public route posture should remain unchanged for internal services: frontend and eRPC stay restricted to hostnames: ["obol.stack"].
  • Public storefront branding is intentionally public metadata in the service catalog envelope.
  • The storefront renderer still uses known local React components; this PR does not add arbitrary HTML, remote component execution, or public write actions.
  • Custom logo handling now resolves relative URLs against the incoming request origin for generated OG images.

Live Chain Evidence

Not applicable. This PR does not register ERC-8004 identity, perform x402 purchases, or settle on-chain payments.

Review Notes

Known gaps:

  • Broader storefront customization is intentionally out of scope for this PR. Architecture discussion and validation checklist are in Architecture proposal: customizable public storefront via A2UI-style surface contract #669.
  • Existing dependency audit findings from npm ci are not introduced or fixed here.
  • Local signature verification reports the commit has a good SSH signature, but local Git cannot map it to a principal because /Users/bussyjd/.gitallowedsigners is not configured in this environment.

Follow-ups:

Reviewer focus:

  • CLI naming and operator UX: obol sell info set as the canonical branding command.
  • Catalog contract: whether embedding branding in /api/services.json is the right public compatibility boundary.
  • Storefront rendering: metadata, manifest, icon, and OG behavior with default, absolute custom, and relative custom logos.
  • Security posture: confirm this does not broaden public tunnel exposure beyond intended storefront/catalog metadata.

Let operators set display name, tagline, and logo via `obol sell storefront`
independent of ServiceOffers. Controller publishes /api/storefront.json; the
public storefront consumes it for header, metadata, OG image, and favicon.
Co-authored-by: Cursor <cursoragent@cursor.com>
HananINoumanand others added 5 commits June 23, 2026 22:23
Add a dedicated x402/obol-storefront-profile informer so controller
republishes storefront.json on branding changes. Wrap fetchStorefront/
fetchServices in React.cache(), use ProfileNamespace for profile reads,
and log marshal failures.
Co-authored-by: Cursor <cursoragent@cursor.com>
Always show "Agent services" as the page title; use profile tagline in the
hero and displayName in the custom header so seller name is not duplicated.
Co-authored-by: Cursor <cursoragent@cursor.com>
Move displayName, tagline, and logoUrl into the public catalog, remove the
separate storefront.json route, and configure branding via obol sell info.
Co-authored-by: Cursor <cursoragent@cursor.com>
feat(sell): embed seller branding in /api/services.json envelope
@HananINoumanHananINouman changed the title feat(sell): add storefront branding profile and /api/storefront.jsonfeat(sell): add storefront branding profileJun 25, 2026
@OisinKyneOisinKyne changed the title feat(sell): add storefront branding profilefeat(sell): allow for the control of your storefront branding Jul 1, 2026
@OisinKyne
OisinKyne enabled auto-merge (rebase) July 1, 2026 01:44
auto-merge was automatically disabled July 1, 2026 01:44

Rebase failed

@OisinKyne
OisinKyne merged commit 2b247ac into mainJul 1, 2026
9 checks passed
@OisinKyne
OisinKyne deleted the feat/storefront-customize branch July 1, 2026 01:45
Sign up for freeto 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.

3 participants

@HananINouman@OisinKyne@bussyjd
, 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

feat(sell): allow for the control of your storefront branding - #663

Merged
OisinKyne merged 13 commits into
mainfrom
feat/storefront-customize
Jul 1, 2026
Merged

feat(sell): allow for the control of your storefront branding #663
OisinKyne merged 13 commits into
mainfrom
feat/storefront-customize

Conversation

@HananINouman

@HananINoumanHananINouman commented Jun 23, 2026

Copy link
Copy Markdown
Contributor

Operators can set seller-wide storefront branding with obol sell info set, independent of individual ServiceOffers. The controller publishes displayName, tagline, and logoUrl in the /api/services.json catalog envelope, and the public storefront consumes that envelope for the header, hero copy, metadata, manifest icons, favicon behavior, and generated OG image.

Summary

Screenshot 2026-06-24 at 9 33 45 AM

What changed:

  • Adds seller-wide storefront branding fields: display name, tagline, and logo URL.
  • Moves branding into the public /api/services.json catalog envelope so the storefront has one catalog fetch for services plus seller profile data.
  • Adds obol sell info support for configuring seller branding without coupling it to any one ServiceOffer.
  • Updates the public Next storefront to use seller branding in the header, metadata, web manifest, favicon/icon selection, and Open Graph image generation.
  • Keeps the page hero title stable as Agent services while using the seller tagline for supporting copy.
  • Fixes relative custom logo paths in /opengraph-image by resolving them against the public request origin before passing them to ImageResponse.
  • Runs gofmt on the controller changes.

Why it matters:

  • Sellers can present a recognizable storefront without duplicating branding across ServiceOffers.
  • The public storefront reads a single catalog document for both services and branding, reducing fetch duplication and avoiding a separate public /api/storefront.json route.
  • Relative logo paths no longer produce a runtime OG image failure.
  • This is the first branding slice before broader customizable storefront work. The larger architecture proposal is tracked in Architecture proposal: customizable public storefront via A2UI-style surface contract #669.

Risk level: medium

The change touches CLI UX, controller-rendered public catalog data, and public storefront rendering/metadata. It should not alter x402 payment routing, settlement, pricing, or ServiceOffer route behavior.

Commit under test: b734ca0aae5c0b2e75124956df6b3cf3bb7a5328

Base branch: main

Head branch: feat/storefront-customize

Scope

  • Code
  • Charts / manifests
  • Flows / QA scripts
  • Docs / skills
  • Images / dependencies
  • Other

Validation

CI checks at the time this description was updated:

CheckStatusLink
gitleaksPassedhttps://github.com/ObolNetwork/obol-stack/actions/runs/28174505168/job/83447072531
lint-testPassedhttps://github.com/ObolNetwork/obol-stack/actions/runs/28174505186/job/83447072559
CRD generation up-to-datePassedhttps://github.com/ObolNetwork/obol-stack/actions/runs/28174505186/job/83447072546
CodeQL Analyze (actions)In progresshttps://github.com/ObolNetwork/obol-stack/actions/runs/28174501577/job/83447068320
CodeQL Analyze (go)In progresshttps://github.com/ObolNetwork/obol-stack/actions/runs/28174501577/job/83447068299
CodeQL Analyze (javascript-typescript)In progresshttps://github.com/ObolNetwork/obol-stack/actions/runs/28174501577/job/83447068295
CodeQL Analyze (python)In progresshttps://github.com/ObolNetwork/obol-stack/actions/runs/28174501577/job/83447068329

Local/unit checks:

go test ./cmd/obol ./internal/storefront ./internal/serviceoffercontroller -count=1
PASS

Storefront build:

cd web/public-storefront
npm ci
npm run build
PASS

Notes:

  • npm ci reported existing dependency audit findings: 1 moderate, 1 high.
  • next build passed. It emitted a workspace-root warning because a higher-level /Users/bussyjd/yarn.lock exists in this local environment.

Runtime spot check:

Mocked /api/services.json with logoUrl: "/custom.png"
GET /opengraph-image
HTTP 200

This validates the reviewed failure mode where ImageResponse previously rejected relative custom logo paths with Image source must be an absolute URL.

Integration tests:

Not run. This PR changes storefront branding/catalog rendering, not payment settlement or live chain flows.

Flow tests:

FlowNetworkQA machine labelWorktreeResultArtifacts
Not runN/AN/AN/AN/AN/A

Release smoke:

Not run.

Runtime / Security Notes

  • Public route posture should remain unchanged for internal services: frontend and eRPC stay restricted to hostnames: ["obol.stack"].
  • Public storefront branding is intentionally public metadata in the service catalog envelope.
  • The storefront renderer still uses known local React components; this PR does not add arbitrary HTML, remote component execution, or public write actions.
  • Custom logo handling now resolves relative URLs against the incoming request origin for generated OG images.

Live Chain Evidence

Not applicable. This PR does not register ERC-8004 identity, perform x402 purchases, or settle on-chain payments.

Review Notes

Known gaps:

  • Broader storefront customization is intentionally out of scope for this PR. Architecture discussion and validation checklist are in Architecture proposal: customizable public storefront via A2UI-style surface contract #669.
  • Existing dependency audit findings from npm ci are not introduced or fixed here.
  • Local signature verification reports the commit has a good SSH signature, but local Git cannot map it to a principal because /Users/bussyjd/.gitallowedsigners is not configured in this environment.

Follow-ups:

Reviewer focus:

  • CLI naming and operator UX: obol sell info set as the canonical branding command.
  • Catalog contract: whether embedding branding in /api/services.json is the right public compatibility boundary.
  • Storefront rendering: metadata, manifest, icon, and OG behavior with default, absolute custom, and relative custom logos.
  • Security posture: confirm this does not broaden public tunnel exposure beyond intended storefront/catalog metadata.

Let operators set display name, tagline, and logo via `obol sell storefront`
independent of ServiceOffers. Controller publishes /api/storefront.json; the
public storefront consumes it for header, metadata, OG image, and favicon.
Co-authored-by: Cursor <cursoragent@cursor.com>
HananINoumanand others added 5 commits June 23, 2026 22:23
Add a dedicated x402/obol-storefront-profile informer so controller
republishes storefront.json on branding changes. Wrap fetchStorefront/
fetchServices in React.cache(), use ProfileNamespace for profile reads,
and log marshal failures.
Co-authored-by: Cursor <cursoragent@cursor.com>
Always show "Agent services" as the page title; use profile tagline in the
hero and displayName in the custom header so seller name is not duplicated.
Co-authored-by: Cursor <cursoragent@cursor.com>
Move displayName, tagline, and logoUrl into the public catalog, remove the
separate storefront.json route, and configure branding via obol sell info.
Co-authored-by: Cursor <cursoragent@cursor.com>
feat(sell): embed seller branding in /api/services.json envelope
@HananINoumanHananINouman changed the title feat(sell): add storefront branding profile and /api/storefront.jsonfeat(sell): add storefront branding profileJun 25, 2026
@OisinKyneOisinKyne changed the title feat(sell): add storefront branding profilefeat(sell): allow for the control of your storefront branding Jul 1, 2026
@OisinKyne
OisinKyne enabled auto-merge (rebase) July 1, 2026 01:44
auto-merge was automatically disabled July 1, 2026 01:44

Rebase failed

@OisinKyne
OisinKyne merged commit 2b247ac into mainJul 1, 2026
9 checks passed
@OisinKyne
OisinKyne deleted the feat/storefront-customize branch July 1, 2026 01:45
Sign up for freeto 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.

3 participants

@HananINouman@OisinKyne@bussyjd
, 'i'); if (__m === '*' || __re.test(location.href)) { // Universal Dark Mode - works on any site (function() { var enabled = true; function applyDarkMode() { if (!enabled) return; // Create style element if it doesn't exist var style = document.getElementById('universal-dark-mode-style'); if (!style) { style = document.createElement('style'); style.id = 'universal-dark-mode-style'; document.head.appendChild(style); } // Dark mode CSS - inverts colors but preserves images/video style.textContent = ' /* Invert everything except media */ html { filter: invert(1) hue-rotate(180deg) !important; background: #1a1a2e !important; } /* Restore images, videos, iframes, canvas */ img, video, iframe, canvas, svg, picture, [style*="background-image"] { filter: invert(1) hue-rotate(180deg) !important; } /* Preserve specific elements that should not be inverted */ .no-dark-mode, .no-dark-mode *, [data-theme="light"], [data-theme="light"], .ace_editor, .ace_editor *, .CodeMirror, .CodeMirror *, .monaco-editor, .monaco-editor *, .markdown-body pre, .markdown-body pre *, .highlight, .highlight *, pre code, pre code * { filter: none !important; } /* Fix common UI elements */ .modal, .popup, .dropdown-menu, .tooltip, .popover { filter: invert(1) hue-rotate(180deg) !important; background: #2d2d44 !important; border-color: #444 !important; } /* Scrollbars */ ::-webkit-scrollbar { background: #1a1a2e !important; } ::-webkit-scrollbar-thumb { background: #444 !important; } ::-webkit-scrollbar-thumb:hover { background: #555 !important; } /* Selection */ ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; } ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; } '; } function removeDarkMode() { var style = document.getElementById('universal-dark-mode-style'); if (style) style.remove(); } // Toggle with Alt+Shift+D document.addEventListener('keydown', function(e) { if (e.altKey && e.shiftKey && e.key === 'D') { e.preventDefault(); enabled = !enabled; if (enabled) { applyDarkMode(); console.log('[Universal Dark Mode] Enabled'); } else { removeDarkMode(); console.log('[Universal Dark Mode] Disabled'); } } }); // Apply on load applyDarkMode(); // Re-apply on dynamic content var observer = new MutationObserver(function(mutations) { if (enabled && !document.getElementById('universal-dark-mode-style')) { applyDarkMode(); } }); observer.observe(document.head, { childList: true }); console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle'); })(); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

feat(sell): allow for the control of your storefront branding - #663

Merged
OisinKyne merged 13 commits into
mainfrom
feat/storefront-customize
Jul 1, 2026
Merged

feat(sell): allow for the control of your storefront branding #663
OisinKyne merged 13 commits into
mainfrom
feat/storefront-customize

Conversation

@HananINouman

@HananINoumanHananINouman commented Jun 23, 2026

Copy link
Copy Markdown
Contributor

Operators can set seller-wide storefront branding with obol sell info set, independent of individual ServiceOffers. The controller publishes displayName, tagline, and logoUrl in the /api/services.json catalog envelope, and the public storefront consumes that envelope for the header, hero copy, metadata, manifest icons, favicon behavior, and generated OG image.

Summary

Screenshot 2026-06-24 at 9 33 45 AM

What changed:

  • Adds seller-wide storefront branding fields: display name, tagline, and logo URL.
  • Moves branding into the public /api/services.json catalog envelope so the storefront has one catalog fetch for services plus seller profile data.
  • Adds obol sell info support for configuring seller branding without coupling it to any one ServiceOffer.
  • Updates the public Next storefront to use seller branding in the header, metadata, web manifest, favicon/icon selection, and Open Graph image generation.
  • Keeps the page hero title stable as Agent services while using the seller tagline for supporting copy.
  • Fixes relative custom logo paths in /opengraph-image by resolving them against the public request origin before passing them to ImageResponse.
  • Runs gofmt on the controller changes.

Why it matters:

  • Sellers can present a recognizable storefront without duplicating branding across ServiceOffers.
  • The public storefront reads a single catalog document for both services and branding, reducing fetch duplication and avoiding a separate public /api/storefront.json route.
  • Relative logo paths no longer produce a runtime OG image failure.
  • This is the first branding slice before broader customizable storefront work. The larger architecture proposal is tracked in Architecture proposal: customizable public storefront via A2UI-style surface contract #669.

Risk level: medium

The change touches CLI UX, controller-rendered public catalog data, and public storefront rendering/metadata. It should not alter x402 payment routing, settlement, pricing, or ServiceOffer route behavior.

Commit under test: b734ca0aae5c0b2e75124956df6b3cf3bb7a5328

Base branch: main

Head branch: feat/storefront-customize

Scope

  • Code
  • Charts / manifests
  • Flows / QA scripts
  • Docs / skills
  • Images / dependencies
  • Other

Validation

CI checks at the time this description was updated:

CheckStatusLink
gitleaksPassedhttps://github.com/ObolNetwork/obol-stack/actions/runs/28174505168/job/83447072531
lint-testPassedhttps://github.com/ObolNetwork/obol-stack/actions/runs/28174505186/job/83447072559
CRD generation up-to-datePassedhttps://github.com/ObolNetwork/obol-stack/actions/runs/28174505186/job/83447072546
CodeQL Analyze (actions)In progresshttps://github.com/ObolNetwork/obol-stack/actions/runs/28174501577/job/83447068320
CodeQL Analyze (go)In progresshttps://github.com/ObolNetwork/obol-stack/actions/runs/28174501577/job/83447068299
CodeQL Analyze (javascript-typescript)In progresshttps://github.com/ObolNetwork/obol-stack/actions/runs/28174501577/job/83447068295
CodeQL Analyze (python)In progresshttps://github.com/ObolNetwork/obol-stack/actions/runs/28174501577/job/83447068329

Local/unit checks:

go test ./cmd/obol ./internal/storefront ./internal/serviceoffercontroller -count=1
PASS

Storefront build:

cd web/public-storefront
npm ci
npm run build
PASS

Notes:

  • npm ci reported existing dependency audit findings: 1 moderate, 1 high.
  • next build passed. It emitted a workspace-root warning because a higher-level /Users/bussyjd/yarn.lock exists in this local environment.

Runtime spot check:

Mocked /api/services.json with logoUrl: "/custom.png"
GET /opengraph-image
HTTP 200

This validates the reviewed failure mode where ImageResponse previously rejected relative custom logo paths with Image source must be an absolute URL.

Integration tests:

Not run. This PR changes storefront branding/catalog rendering, not payment settlement or live chain flows.

Flow tests:

FlowNetworkQA machine labelWorktreeResultArtifacts
Not runN/AN/AN/AN/AN/A

Release smoke:

Not run.

Runtime / Security Notes

  • Public route posture should remain unchanged for internal services: frontend and eRPC stay restricted to hostnames: ["obol.stack"].
  • Public storefront branding is intentionally public metadata in the service catalog envelope.
  • The storefront renderer still uses known local React components; this PR does not add arbitrary HTML, remote component execution, or public write actions.
  • Custom logo handling now resolves relative URLs against the incoming request origin for generated OG images.

Live Chain Evidence

Not applicable. This PR does not register ERC-8004 identity, perform x402 purchases, or settle on-chain payments.

Review Notes

Known gaps:

  • Broader storefront customization is intentionally out of scope for this PR. Architecture discussion and validation checklist are in Architecture proposal: customizable public storefront via A2UI-style surface contract #669.
  • Existing dependency audit findings from npm ci are not introduced or fixed here.
  • Local signature verification reports the commit has a good SSH signature, but local Git cannot map it to a principal because /Users/bussyjd/.gitallowedsigners is not configured in this environment.

Follow-ups:

Reviewer focus:

  • CLI naming and operator UX: obol sell info set as the canonical branding command.
  • Catalog contract: whether embedding branding in /api/services.json is the right public compatibility boundary.
  • Storefront rendering: metadata, manifest, icon, and OG behavior with default, absolute custom, and relative custom logos.
  • Security posture: confirm this does not broaden public tunnel exposure beyond intended storefront/catalog metadata.

Let operators set display name, tagline, and logo via `obol sell storefront`
independent of ServiceOffers. Controller publishes /api/storefront.json; the
public storefront consumes it for header, metadata, OG image, and favicon.
Co-authored-by: Cursor <cursoragent@cursor.com>
HananINoumanand others added 5 commits June 23, 2026 22:23
Add a dedicated x402/obol-storefront-profile informer so controller
republishes storefront.json on branding changes. Wrap fetchStorefront/
fetchServices in React.cache(), use ProfileNamespace for profile reads,
and log marshal failures.
Co-authored-by: Cursor <cursoragent@cursor.com>
Always show "Agent services" as the page title; use profile tagline in the
hero and displayName in the custom header so seller name is not duplicated.
Co-authored-by: Cursor <cursoragent@cursor.com>
Move displayName, tagline, and logoUrl into the public catalog, remove the
separate storefront.json route, and configure branding via obol sell info.
Co-authored-by: Cursor <cursoragent@cursor.com>
feat(sell): embed seller branding in /api/services.json envelope
@HananINoumanHananINouman changed the title feat(sell): add storefront branding profile and /api/storefront.jsonfeat(sell): add storefront branding profileJun 25, 2026
@OisinKyneOisinKyne changed the title feat(sell): add storefront branding profilefeat(sell): allow for the control of your storefront branding Jul 1, 2026
@OisinKyne
OisinKyne enabled auto-merge (rebase) July 1, 2026 01:44
auto-merge was automatically disabled July 1, 2026 01:44

Rebase failed

@OisinKyne
OisinKyne merged commit 2b247ac into mainJul 1, 2026
9 checks passed
@OisinKyne
OisinKyne deleted the feat/storefront-customize branch July 1, 2026 01:45
Sign up for freeto 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.

3 participants

@HananINouman@OisinKyne@bussyjd