Drive the OpenWork Cloud dashboard (Den Web / app.openworklabs.com) as a real user via headless Chrome CDP — sign up, create an org, invite teammates, teams, plugins with skills, marketplaces, team access grants, desktop handoff. Use for cloud tutorials, dashboard screenshots, demo walkthroughs, or when a task says \"create an org / invite teammates / create a plugin / assign a marketplace\" on OpenWork Cloud.
Scanned 9/12/2026
Install to Claude Code
npx -y skills add thedixitjain/the-mega-skill-library --skill cloud-dashboard-walkthrough --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Cloud Dashboard Walkthrough?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/thedixitjain-cloud-dashboard-walkthrough)More formats (shields.io, HTML) on the badges page.
---
name: cloud-dashboard-walkthrough
description: "Drive the OpenWork Cloud dashboard (Den Web / app.openworklabs.com) as a real user via headless Chrome CDP — sign up, create an org, invite teammates, teams, plugins with skills, marketplaces, team access grants, desktop handoff. Use for cloud tutorials, dashboard screenshots, demo walkthroughs, or when a task says \"create an org / invite teammates / create a plugin / assign a marketplace\" on OpenWork Cloud."
category: devops-and-infra
source_repo: different-ai/openwork
source_path: ".opencode/skills/cloud-dashboard-walkthrough/SKILL.md"
source_url: https://github.com/different-ai/openwork/blob/HEAD/.opencode/skills/cloud-dashboard-walkthrough/SKILL.md
---
# Cloud Dashboard Walkthrough (Den Web via CDP)
Drive the real OpenWork Cloud dashboard end-to-end as a user. Proven flow used
to produce `packages/docs/cloud/team-quickstart.mdx` — reuse it for
tutorial refreshes, demos, and screenshot runs.
## Stack setup
Start a Den server sandbox (multi-org, dev mode skips email verification):
```bash
bash .devcontainer/test-server-on-daytona.sh dev --name <sandbox-name>
# capture the printed DEN_WEB_URL and DEN_API_URL
```
`start-daytona-server.sh` must pass `DEN_ORG_MODE` to **den-web** (not just
den-api); otherwise den-web defaults to `single_org` with private signup and
the UI silently routes new emails to the password step. Verify:
```bash
curl -s "$DEN_WEB_URL/api/runtime-config" # expect "orgMode":"multi_org"
```
Launch a driver Chrome (2x screenshots, isolated profile):
```bash
"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" \
--headless=new --remote-debugging-port=9223 \
--user-data-dir=/tmp/opencode/chrome-profile \
--window-size=1440,960 --force-device-scale-factor=2 \
--hide-scrollbars --disable-gpu about:blank &
```
Then use `browser_navigate` / `browser_eval` / `browser_screenshot` with
`browser_url: "http://127.0.0.1:9223"`. The a11y snapshot is sparse in
headless — drive everything through `browser_eval` DOM queries instead.
## Driving patterns (React/Next)
- **Inputs**: set values through the native setter so React sees them:
```js
const set = Object.getOwnPropertyDescriptor(HTMLInputElement.prototype, "value").set;
set.call(input, "value"); input.dispatchEvent(new Event("input", { bubbles: true }));
```
(Use `HTMLTextAreaElement.prototype` for textareas.)
- **Buttons**: match on exact trimmed text. Beware prefix collisions — the
submit "Sign up" vs "Sign **up with Google**" (clicking the latter on a
sandbox yields "Provider not found").
- **Before every screenshot**: hide the Next.js dev badge —
`document.querySelector('nextjs-portal')?.style.display = 'none'` — and wait
~1s for settle. Dev-only UI is safe to hide; never hide product UI.
- Tab labels carry count badges (`Teams2`): match with
`el.textContent.trim().replace(/\d+$/, "")`.
## The flows (routes + exact labels)
| Step | Route | Key labels |
|---|---|---|
| Email-first sign-in | `/` | "Start using OpenWork" → EMAIL → **Next** |
| Sign-up | `/` | "Create your account." → EMAIL/NAME/PASSWORD → **Sign up** |
| Create org | `/organization` | "Name your team." → Organization name → **Continue** |
| Onboarding checklist | `/dashboard/onboarding` | "Set up {org}" → Step 1 of 2 install, Step 2 of 2 model |
| Members / invites | `/dashboard/members` | **Add member** → Email + Role → **Send invite**; rows show INVITED/Pending |
| Teams | `/dashboard/members` Teams tab | **Create Team** → name (placeholder "Core Engineering") + member card toggles → **Create team** |
| Plugins list | `/dashboard/plugins` | **Create plugin** |
| Plugin editor | `/dashboard/plugins/new` | name/description → **+ Skill** (name, one-line description, markdown instructions) → Share: org-wide checkbox + **Marketplace** select → **Create plugin** |
| Marketplaces | `/dashboard/marketplaces` | **New marketplace** → Name + Description → **Create marketplace** |
| Marketplace access | `/dashboard/marketplaces/<id>` Members tab | "Who can access this": Everyone toggle, **Add team**, **Add people** |
Notes:
- The plugin editor pre-selects the first marketplace in the Share section —
create your marketplace *before* the plugin.
- Skills are stored as SKILL.md-style config objects; write instructions as a
plain markdown runbook.
- **Security check**: changing marketplace access triggers a sudo modal
("For security, confirm it's you…"). Fill `input[type="password"]`, click
**Verify password**; the pending action retries automatically.
- **Seat limit**: invites beyond 5 members return 402 and open the
"Subscribe to add more users" dialog (free tier = 5 seats).
## Teammates actually joining
Invite tokens are readable as the owner: `GET /api/den/v1/org` →
`invitations[].token`. Join link: `/join-org?invite=<token>`.
- **Browser path** (for "what the teammate sees" screenshots): second Chrome
profile on another port → open join link → set password → **Join {org}**.
- **API path** (fast): `POST $DEN_API_URL/api/auth/sign-up/email` with the
invited email (dev mode returns a token immediately), then
`POST /v1/orgs/invitations/accept` with `Authorization: Bearer <token>` and
body `{"id":"<inviteToken>"}`.
- Accounts created through the join flow get the default name "OpenWork User";
fix via `PATCH /api/den/v1/me/profile` `{"firstName":"…","lastName":"…"}`
from that user's session.
## Desktop handoff grants
As a signed-in web user: `POST /api/den/v1/auth/desktop-handoff` (body `{}`)
→ `{ grant }`. Build the deep link yourself — the server-resolved
`denBaseUrl` can be an internal host:
```
openwork://den-auth?grant=<grant>&denBaseUrl=<urlencoded DEN_WEB_URL>
```
Grants expire in 5 minutes and are single-use. Consuming it in Electron is
covered in the `daytona-electron-den` skill.
## Daytona preview URLs expire
Public preview URLs get auth-walled after a while (redirect to Auth0 →
fetches fail / "Not found."). Recovery:
```bash
daytona sandbox preview-url <sandbox> -p 3005 --expires 86400 # den-web
daytona sandbox preview-url <sandbox> -p 8788 --expires 86400 # den-api
```
Then **restart the Den stack with the signed URLs as its public URLs** —
Better-Auth rejects the new host with 403 "Invalid origen" otherwise (trusted
origens are derived from the public URLs at startup). Re-run
`start-daytona-server.sh` inside the sandbox with
`DEN_WEB_PUBLIC_URL`/`DEN_API_PUBLIC_URL` set to the signed URLs. Browser
cookies do not carry across hosts — sign in again.
## daytona exec quirk
The CLI eats flag-like tokens inside commands (`mkdir -p`, `tail -30` lose
their flags). Prefer flag-free forms (`cd /workspace && mkdir x`,
`cat file | tail`) or pipe the file to stdout and process locally.
---
**Source:** [`different-ai/openwork`](https://github.com/different-ai/openwork) → `.opencode/skills/cloud-dashboard-walkthrough/SKILL.md`
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!