← Back to skills

Domain skill

vercel

Markdown synced from browser-harness domain skills.

Agent prompt

Use this skill

Copy this prompt into your coding agent to make it enable browser-harness domain skills and read this exact domain folder before automating.

Set up https://github.com/browser-use/browser-harness for me if it is not already installed. If setup is needed, read `install.md` first to install and connect it to my real browser. Then read `SKILL.md` for normal usage and always read `helpers.py` because that is where the browser-harness functions are.

Enable domain skills if they are not already enabled by setting `BH_DOMAIN_SKILLS=1` for browser-harness. Use the `vercel` domain skill from `agent-workspace/domain-skills/vercel/`. Read every markdown file for this domain before inventing an approach:
- agent-workspace/domain-skills/vercel/archive-and-audit.md
- agent-workspace/domain-skills/vercel/observability.md
- agent-workspace/domain-skills/vercel/vercel.md

Use those domain-skill notes to complete my task for `vercel` in my real browser. When you open a setup, verification, or task tab, activate it so I can see the active browser tab.

Skill contents

What the agent will read

project identification and archival checks

archive-and-audit.md

Source
  • Use the existing authenticated browser for project dashboards; prefer the public GitHub API/git for source archival once the repository is known. This guide does not require exporting cookies or environment-variable...
  • Team overview: https://vercel.com/<team>.
  • Project overview: https://vercel.com/<team>/<project>.
  • Project analytics: https://vercel.com/<team>/<project>/analytics.
Show full markdown

Use the existing authenticated browser for project dashboards; prefer the public GitHub API/git for source archival once the repository is known. This guide does not require exporting cookies or environment-variable values.

Identity and routes

  • Team overview: https://vercel.com/<team>.
  • Project overview: https://vercel.com/<team>/<project>.
  • Project analytics: https://vercel.com/<team>/<project>/analytics.
  • Production Deployment on the overview exposes the source repository, branch, abbreviated commit, full commit link, deployment domain, and creation date. Compare the full commit with the archived Git checkout; do not assume default-branch HEAD is deployed.
  • A 404 on a known team route may be account mismatch, not a missing project. Read the rendered account identity after hydration.
  • Use an existing tab from the intended Chrome profile. Target.createTarget does not guarantee that profile. Verify the visible Vercel account before reading project data. If no matching tab exists, ask the user to open the intended profile. Do not copy its credential store.
  • Navigation completion is not dashboard hydration completion. After wait_for_load(), verify the visible account/project text and take a new screenshot before concluding that a team is unavailable.

Read-only audit boundaries

The overview may show an Action Required / vulnerable-dependencies banner. Save the visible warning and its destination link. Remediation pages can initialize code-generation workflows, so do not navigate into a fix workflow merely to inspect a warning. Repository versions and official advisories are sufficient for initial verification. Do not click Redeploy, Update, or Rotate unless the user authorized that action.

Analytics reports are scoped to the displayed date range and can contain tiny samples. Save the date range alongside counts; do not interpret 100% bounce on a single-page site as proof that all readers disliked it. Custom-event availability depends on the account plan.

Static media traps

A .mp4 URL can return HTTP 200 with Content-Type: video/mp4 but contain a Git LFS pointer, not video. The body starts with version https://git-lfs.github.com/spec/v1 and is only about 130 bytes. Check bytes/magic and decode media, not just status codes.

For a complete source archive:

  1. Clone source and record the exact production commit.
  2. Fetch needed/all referenced LFS objects and check integrity.
  3. Preserve hydrated working-tree media and .git/lfs/objects.
  4. A git bundle --all preserves Git history but not LFS object bodies; retain the full source directory too.
  5. Capture external CDN delivery URLs separately. Versioned and unversioned URLs can serve identical bytes; record URL-to-hash mappings rather than assuming every URL is a distinct work.
  6. Preserve already-broken live responses as evidence and list recovered originals separately. Do not silently replace historical failures with guessed assets.

project identity, visitor analytics and request traffic

observability.md

Source
  • The contributor supplied these observations without a validation date. Verify current labels and routes in the visible dashboard.
  • Team overview: /{teamslug}.
  • Project overview: /{teamslug}/{projectslug}.
  • A repository can be linked to multiple Vercel projects. Match the live domain
Show full markdown

The contributor supplied these observations without a validation date. Verify current labels and routes in the visible dashboard.

Resolve the actual project first

  • Team overview: /{team_slug}.
  • Project overview: /{team_slug}/{project_slug}.
  • A repository can be linked to multiple Vercel projects. Match the live domain on the project's Production Deployment card, not just a similar project name.
  • The production card shows its source commit. A newer failed deployment does not replace the live commit. Record web and separately hosted backend revisions independently.

Visitor analytics versus operational traffic

  • Project Analytics links to the visitor dashboard. An Enable button and Demo Data label mean the sample chart is not measured visitor activity.
  • Project Observability → Edge Requests provides operational request counts even when visitor analytics is not enabled.
  • The edge-request view supports Routes, Paths, and Bot Name groupings. Inspect the exact time range and environment (e.g. Production).
  • Page hits, sign-in route requests, function invocations and edge requests are not counts of people, successful sign-ins or conversions. The requesting agent, bots, scanners, static assets and prefetches may contribute.
  • Named-bot counts do not imply the unclassified remainder is human.
  • Longer lookback choices can be gated behind an observability plan. Do not enable/upgrade a paid feature just to answer a traffic question.

UI traps

  • Edge Requests may be both a sidebar link and a card link with identical destinations. Scope to the known navigation region or disambiguate the links.
  • Client-side navigation may return a stale previous-page snapshot immediately after clicking. Check URL/next state rather than repeating the click blindly.
  • A deployment's Logs page may show runtime request logs, not build logs. No runtime entries does not explain why a build failed.

Keep account names, customer domains, project IDs and traffic measurements out of reusable public skills.

Vercel Dashboard

vercel.md

Source
  • Field-tested against vercel.com on 2026-05-03/04 using a logged-in Chrome session and the browser cookie auth pattern below.
  • pageinfo()["url"] after navigating /dashboard gives you the real /<team-slug> URL.
  • State filter: append &state=READY|ERROR|CANCELED|BUILDING|QUEUED|INITIALIZING Target filter: append &target=production|preview|development
  • Deployment object keys: uid, name, projectId, url, created, source, state, readyState, readySubstate, type, creator, inspectorUrl, meta, target, aliasError, aliasAssigned, isRollbackCandidate, createdAt, buildingAt,...
Show full markdown

Field-tested against vercel.com on 2026-05-03/04 using a logged-in Chrome session and the browser cookie auth pattern below.

Auth — browser cookies, no separate token needed

python
import json
cookies = cdp("Network.getCookies", urls=["https://vercel.com"])
parts = [c["name"] + "=" + c["value"] for c in cookies.get("cookies", [])]
headers = {"Cookie": "; ".join(parts), "Accept": "application/json"}

URL patterns

code
/dashboard                                            → redirects to /<team-slug>
/<team-slug>                                          → projects overview
/<team-slug>/<project>/deployments                   → deployment list
/<team-slug>/~/deployments                           → all-team deployments
/<team-slug>/<project>/<uid-no-prefix>                → deployment inspector
/<team-slug>/<project>/<uid-no-prefix>/logs           → runtime logs tab (requests, not build)
/<team-slug>/<project>/logs?deploymentIds=<dep["uid"]> → runtime logs scoped to one deploy (dep["uid"] includes dpl_ prefix)

page_info()["url"] after navigating /dashboard gives you the real /<team-slug> URL.

REST API

List deployments

python
resp = http_get(
    "https://vercel.com/api/v6/deployments?limit=100&teamId=<team-slug>",
    headers=headers
)
# teamId accepts the URL slug (e.g. "my-team") — confirmed working.
# Vercel also has a separate internal team ID (team_xxx); slug is more practical here.
data = json.loads(resp)
deps = data["deployments"]          # list of deployment objects
next_ts = data["pagination"]["next"] # pass as &until=<ts> to paginate; None when done

State filter: append &state=READY|ERROR|CANCELED|BUILDING|QUEUED|INITIALIZING Target filter: append &target=production|preview|development

Deployment object keys: uid, name, projectId, url, created, source, state, readyState, readySubstate, type, creator, inspectorUrl, meta, target, aliasError, aliasAssigned, isRollbackCandidate, createdAt, buildingAt, ready, projectSettings

dep["inspectorUrl"] gives the correct inspector URL directly — use it rather than constructing the URL manually. dep["uid"] is the full dpl_<...> string for API calls; URL paths use the same string with the dpl_ prefix stripped.

List projects

python
data = json.loads(http_get(
    "https://vercel.com/api/v9/projects?teamId=<team-slug>&limit=50",
    headers=headers
))
# data["projects"][i]["latestDeployments"] → recent deploys per project

Build log

python
import json, re

dep = deps[0]      # a deployment object from the list above; swap index as needed
uid = dep["uid"]   # e.g. "dpl_2tySoj6ceJkTgtsWHvd5r1Hpgyd1" — already includes dpl_ prefix
resp = http_get(
    "https://vercel.com/api/v3/deployments/" + uid + "/events?builds=1&limit=5000&teamId=<team-slug>",
    headers=headers
)
# No pagination cursor in response — all events returned in one shot.
# limit=5000 is a safe ceiling. limit=-1 does NOT work (returns empty).
# API event count differs from the "N lines" shown in the UI header — do not use that as limit.
# Response is a JSON array, one object per line, separated by ",\n"
lines = [l.strip().rstrip(",") for l in resp.strip().split("\n") if l.strip() not in ("[", "]", "")]
events = [json.loads(l) for l in lines]
# Strip ANSI escape codes from text field
clean = "\n".join(re.sub(r"\x1b\[[0-9;]*m", "", e["text"]) for e in events)

Event schema: {created, date, deploymentId, id, text, type: "stdout"|"stderr", serial, info: {type: "build", name: "bld_<id>", entrypoint: "."}}

Scraping projects and deployment status

Fastest approach — document.body.innerText is reliable; the Projects section renders near the end:

python
new_tab("https://vercel.com/dashboard")
wait_for_load()
text = js("document.body.innerText")
# Each project card block in innerText (confirmed live):
#   <project-name>\n<commit msg>\n<date>\n on\n<branch>
# Note: .vercel.app and <owner>/<repo> are separate link elements, not in this text block

For deployment links specifically (inspector URLs contain the project name):

python
# Replace <project-name> with the actual project slug
links = js("Array.from(document.querySelectorAll('a[href]')).filter(a=>a.href.includes('/<project-name>/')).map(a=>a.href+'|'+a.innerText.trim().slice(0,80)).join('||')")

Deployment inspector page structure

URL: /<team-slug>/<project>/<uid-no-prefix> — title: <project> – Deployment Overview – Vercel

Tabs across the top: Deployment | Logs | Resources | Source | Open Graph

Accordion sections (all expand on click):

  1. Deployment Settings — build machine, Node.js version, protection, etc. Shows "N Recommendations" badge when Vercel has upsell suggestions.
  2. Build Logs — header shows duration + N lines (UI line count) + warning count + ✅/❌. Content is a virtual list — only visible rows are in the DOM. Use the API endpoint above to get all lines. Note: the UI line count does not equal the API event count.
  3. Deployment Summary — resource breakdown
  4. Deployment Checks — external check integrations
  5. Assigning Custom Domains — alias assignment status

Bottom cards: Runtime Logs | Observability | Speed Insights | BotID

Runtime logs page structure

URL: /<team-slug>/<project>/<uid-no-prefix>/logs — title: <project> – Deployment Runtime Logs – Vercel

This is request/response logs (serverless function traffic), not build output. Left panel filters: Timeline, Console Level (Warning/Error/Fatal with counts), Resource, Environment, Route, Request Path, Status Code, Request Type, Host, Request Method, Cache, Branch, Workflow Run, Workflow Step.

Gotchas

  • /dashboard always redirects — canonical URL is /<team-slug>. Always check page_info()["url"] after navigation.
  • Build logs are in a virtual list — document.body.innerText only contains what's currently scrolled into view. Use /api/v3/deployments/<dep["uid"]>/events to get all lines.
  • Build log text has ANSI escape codes — strip with re.sub(r"\x1b\[[0-9;]*m", "", text) before displaying.
  • Short UID vs full UID — dep["uid"] = dpl_2tySoj6ceJkTgtsWHvd5r1Hpgyd1 (full, with prefix). URL paths strip the dpl_ prefix but keep the full string: /<team-slug>/<project>/2tySoj6ceJkTgtsWHvd5r1Hpgyd1. The breadcrumb displays a truncated form (2tySoj6ce) but that is not the URL. dep["inspectorUrl"] gives you the correct URL directly.
  • Preview deployment URLs follow <project>-git-<branch-slug>-<team-slug>.vercel.app. The branch slug is truncated with a hex suffix (e.g. vercel/install-analytics → vercel-install-v-f236ab).
  • Status filter shows 5/6 by default — Canceled is excluded from the deployments list by default. The 6 states in order: Ready (green), Error (red), Building (orange), Queued, Initializing, Canceled. DOM marker: aria-label="N of 6 statuses selected" on the badge.
  • "Error: Forbidden" in the preview thumbnail = the deployed app requires auth, not a deployment failure.
  • Project card ! icon = Speed Insights performance alert, not a build error.
  • Page title prefix is a status signal — 🟢 Vercel / 🟢 <project> = all systems nominal.
  • Hobby plan: Alerts (anomaly monitoring) requires Pro. Deployment Settings shows "N Recommendations" for plan-upsell config suggestions.