| name | noon-shared |
| description | Common noon Seller Center mechanics — login (OTP auto-fetch), page-structure URL map, My Catalog read access, common modals, button-click patterns, project-ID discovery. Prerequisite: every other noon-* skill (noon-listing, noon-fbn, noon-exports, noon-ads) expects this loaded for auth and shared UI patterns. |
Noon — Shared (login, navigation, common patterns)
This skill covers what every noon Seller Center task needs:
authentication, the page-structure URL map, My Catalog read access,
and shared UI patterns (modals, button clicks). Operation-specific
skills (noon-listing, noon-fbn, noon-exports, noon-ads)
load this first.
1. Login — Auto-fetch OTP When Email Is Bound
Noon uses email OTP only (no password). Before doing ANYTHING,
decide how the OTP will be retrieved — do NOT bother the user if an
email MCP integration can do it for you.
Decision flow (follow in order, do NOT skip steps)
-
Open the login page and look at the email it's about to send OTP to:
browser-use open "https://login.noon.partners/en/"
sleep 3 && browser-use state
Ziniao often auto-fills or remembers a session. The page shows
Log in with OTP sent to <email>.
-
Check whether the task prompt includes a "## Email System"
section (the runner injects it when the store has connected
email accounts). Compare the bound emails to the Noon login
email shown on screen:
- Match → fetch the OTP yourself via email MCP (Case A).
- No email system section, OR emails do not match →
ask the user (Case B). Never guess — mismatched emails mean
a different inbox.
Case A — Auto-fetch OTP via email MCP (preferred)
This works when the bound email address equals the Noon login
email. One round trip, no user prompt:
vibe_seller_sync_email_now(account_email='<bound-email>')
vibe_seller_email_info(store_id='<store-id>')
Then read the latest Noon OTP email. The body is HTML — the 6-digit
code sits on its own line inside a styled <div>. Extract it with
a regex on body_html (not body_text, which has escaped markup):
sqlite3 <db_path> "SELECT body_html FROM emails \
WHERE folder='INBOX' \
AND sender LIKE '%verify@noon.com%' \
AND subject='Verify your email' \
ORDER BY date DESC LIMIT 1" \
| python3 -c "
import sys, re
html = sys.stdin.read()
# The OTP is a standalone 6-digit number inside a styled div.
# Reject repeated digits (000000, 333333 etc. — those are hex colors).
for m in re.findall(r'>\s*(\d{6})\s*<', html):
if len(set(m)) > 1:
print(m); break
"
Then fill it and continue:
browser-use input <otp-input> "<code>"
browser-use click <continue-btn>
browser-use state
browser-use click <maybe-later-btn>
Don't ask the user at all in Case A. The whole point of the
binding is that the agent can finish login unattended.
Case B — Ask the user (only when Case A doesn't apply)
Trigger the OTP, then ask via AskUserQuestion (which requires
2+ options, not 1 — a single-option call fails validation):
AskUserQuestion(questions=[{
"question": "I've triggered the Noon OTP email to <email>. Please enter the 6-digit code in the browser, then tell me when you're ready.",
"header": "OTP",
"options": [
{"label": "Entered, continue", "description": "I typed the OTP"},
{"label": "Didn't arrive", "description": "Resend or switch account"}
],
"multiSelect": false
}])
If the user can't receive the OTP, don't guess or retry — escalate
and let them resolve.
After login — discover {project_id} from the URL
browser-use click <maybe-later-btn>
Do NOT ask the user for the project ID if the store profile
(stores/<slug>/STORE.md) doesn't have it. Read it from the post-
login URL — the welcome / store-home page always carries
?project=PRJ{project_id} (e.g. NNNNNN). Capture it once, then
reuse for the rest of the task. A project's countries share the same
numeric project ID; only the URL country suffix (/en-<cc>/) differs.
Optionally persist what you learned back to the store profile:
vibe_seller_write_workspace_file(
path="stores/<slug>/metadata.json",
content='{"platform_countries": {"noon": ["EG", "KW"]}, "noon_project_id": "<project_id>"}'
)
2. Page Structure Cheat Sheet
Most post-login URLs require ?project=PRJ{project_id} (the login
and welcome pages are the only exceptions). {project_id} is the
numeric project identifier. The store identifier in path segments
like STR{project_id}-N{CC} reuses the same numeric value with
STR prefix and country suffix. Direct URL navigation works for
most pages; sidebar only for Support/Help.
| Page | URL |
|---|
| Create listing | noon-catalog.noon.partners/en/catalog/create |
| Edit listing | noon-catalog.noon.partners/en/catalog/{sku}/d?code={code}&offerTab=noon |
| My Catalog | noon-catalog.noon.partners/en/catalog |
| Catalog Imports | noon-catalog.noon.partners/en/imports |
| Catalog Exports | noon-catalog.noon.partners/en/exports |
| FBN My ASN & Storage | fbn.noon.partners/en-{cc}/asn |
| FBN Create ASN | fbn.noon.partners/en-{cc}/asn/createasn |
| FBN My Inventory | fbn.noon.partners/en-{cc}/inventory |
| Sales | reports.noon.partners/en/sales/ |
| Transaction View | noon-payments.noon.partners/en/transaction-view |
| Ad Manager | admanager.noon.partners/en-{cc}/home?mpCode=noon |
| Campaign Detail | admanager.noon.partners/en-{cc}/campaign/details/{id}?mpCode=noon |
| Create Campaign | admanager.noon.partners/en-{cc}/campaign/start?mpCode=noon |
| Vantage | vantage.noon.partners/en/ |
3. My Catalog (read access)
URL: https://noon-catalog.noon.partners/en/catalog?project=PRJ{project_id}
Tabs: noon (default), supermall, global.
Each row has:
- Product title + Brand
- PSKU (Partner SKU) + SKU (noon ID), copyable
- Price, Sale/Promo badge
- Estimated Fees (FBN + FBP separately)
- Active Net Stock (FBN + FBP, links to inventory)
- Performance (Views, Units Sold, Sales)
- Seller Status toggle
- Live Status + "View Issues" link
Click the product title anchor to open the edit page (see
noon-listing skill).
For ad-tuning audits, this catalog read is the prerequisite step
that establishes "what the SKU actually is" before reading any
campaign — see noon-ads/references/ads-tuning.md.
4. Common Modals
Save Changes Warning
When leaving a page with unsaved changes:
"Do you want to save the changes you made to this page?"
[Discard Changes] [Save Changes]
Always click Save Changes unless intentionally reverting.
Penalty Warning (ASN)
Before reserving FBN quota — see noon-fbn skill. Click Cancel
to exit without commitment.
Tour Modal
First-time visits show tours. Dismiss with "Skip for now".
Hotjar Survey
NPS survey at bottom-right. Dismiss with aria-label="Hide survey".
Passkey Prompt (After Login)
Dismiss with "Maybe Later".
5. Button Clicking Patterns
JS Click for Off-Screen Buttons
Listing wizard "Next" buttons are often outside viewport:
browser-use eval "
var r=''; document.querySelectorAll('button').forEach(function(b,i){
r+=i+':'+b.textContent.trim().substring(0,30)+':d='+b.disabled+' | ';
}); r
"
browser-use eval "document.querySelectorAll('button')[0].click()"
Iframe Sidebar Clicks
Toolbar iframe is cross-origin; use get bbox on the parent
category button, then click below it at estimated offset:
browser-use click <category-btn>
browser-use get bbox <category-btn>
browser-use click <x+35> <y+50>
6. Tips (general)
- Always use direct URLs for known pages (faster, more reliable).
- Login OTP — prefer email MCP over asking the user. If the
store has a bound email account matching the Noon login email,
fetch the OTP yourself (Case A). Only ask when no binding applies.
- Project ID is required in the URL:
?project=PRJ{project_id}.
- Country switching varies by page — Sales/Transaction use bottom-left
store dropdown; Ad Manager uses URL country suffix; FBN paths embed
the country code directly. Check per-page.
- Save changes before navigating — warning modal can silently
lose data if you click Discard.
browser-use input <idx> <value> vs browser-use type <value>.
input targets an element by index; type types into whatever is
currently focused. They are not interchangeable — type <idx> <value> fails with a usage error.
AskUserQuestion needs 2+ options — a single-option call
fails schema validation; always give at least a confirm and a
"didn't work" option.
- Captures →
/tmp/<run-slug>/. Per-run live data goes to a
temp dir, never under ~/.vibe-seller/knowledge/.
See also
noon-listing — create / edit SKUs (price, stock, content)
noon-fbn — FBN/ASN, inventory, barcode print
noon-exports — Sales report, Transaction View, Catalog Exports
noon-ads — Ad Manager (campaigns, tuning, keyword research, negatives)