Commit Graph

757 Commits

Author SHA1 Message Date
Tommy D. Rossi 9ab7233d6a website: enable prerender for index route 2026-02-20 22:28:59 +01:00
Tommy D. Rossi 8eee5ce5d4 skill: add preference note to playwriter description
Clarify in the skill frontmatter that playwriter should be used over
other Playwright MCPs since it connects to the user's existing Chrome
instead of launching a new browser instance.
2026-02-20 22:18:13 +01:00
Tommy D. Rossi 44b367a927 website: fix dark mode, table contrast, prose opacity, add AGENTS.md
Dark mode fix: import liveline.css and liveline-prism.css via CSS @import
in globals.css instead of JS import in the route file. This brings them
into the Tailwind compilation chain so @variant dark works. @variant dark
silently fails in CSS files imported only via JS — documented this
constraint in website/AGENTS.md.

- Prism dark colors use CSS variables on :root with @variant dark
- liveline.css dark overrides use @variant dark nested inside selectors
- Table cells use --ll-text-primary for full contrast in both modes
- Prose paragraphs at 0.82 opacity, bold and inline code punch through
  to full opacity for visual hierarchy
- Prose line-height increased to 22px
- Add website/AGENTS.md documenting dark mode rules
2026-02-20 17:20:09 +01:00
Tommy D. Rossi b2ab69c236 website: bold keywords in every paragraph, saturated prism colors, font-weight 500 for code
- Add <strong> to every paragraph so each has at least one bold keyword
- Increase light mode Prism saturation: brighter purple, amber, green, blue
- Set font-weight 500 for code blocks and inline code
- Add letter-spacing 0.02em to code blocks and inline code
2026-02-20 16:06:45 +01:00
Tommy D. Rossi b7f02ac9f4 website: add transparent PNG favicons, typed meta/links exports, OG image
- Replace favicon.ico with transparent PNG favicons (32px, 16px) generated
  from the gray extension icon, preserving alpha channel
- Move favicon links from hardcoded JSX to typed LinksFunction export in
  root.tsx, rendered via <Links /> component
- Type liveline meta export as MetaFunction
- Add properly sized OG image (1200x630) for X/Slack/Discord previews,
  update meta tags to reference it
2026-02-20 15:57:12 +01:00
Tommy D. Rossi 3917c5137d website: clean up liveline page, fix dark mode, add OG tags
- Remove 5 ChartPlaceholder stubs that were never replaced with real content
- Add OG meta tags (title, description, og:image 1280x800, twitter:card
  summary_large_image) for rich previews on X, Slack, Discord
- Rename PropsTable to ComparisonTable with configurable headers prop,
  fixing the hardcoded 'Prop/Type/Default' headers on comparison tables
- Remove stale Antigravity/Jetski comparison section
- Switch dark mode from .dark class toggle to prefers-color-scheme media
  query via Tailwind @custom-variant. Remove inline JS script from root.tsx,
  update all .dark selectors in liveline.css, liveline-prism.css to use
  @variant dark from globals.css so strategy is defined in one place
- Fix scrollbar colors: light gray on light backgrounds, subtle white on
  dark backgrounds (was using --color-muted which was invisible in both)
- Update remote access section with traforo link, VPN/firewall context,
  MCP env var docs, and more use cases from docs/remote-access.md
2026-02-20 15:44:16 +01:00
Tommy D. Rossi 11b615c297 add screenshot 2026-02-20 15:26:53 +01:00
Tommy D. Rossi 0032c65212 Update pnpm-lock.yaml 2026-02-20 15:26:36 +01:00
Tommy D. Rossi e7b7aad8a9 Update liveline.tsx 2026-02-20 15:26:34 +01:00
Tommy D. Rossi 5f764ed200 test(snapshot): speed up aria-label screenshot coverage
Optimize the real-page aria label screenshot integration test by reducing page load overhead (parallel page setup and lighter load wait), while keeping meaningful coverage on complex public pages.

Use old.reddit.com and Hacker News for coverage, preserve label rendering and screenshot assertions, and bump playwriter version/changelog.
2026-02-20 15:22:04 +01:00
Tommy D. Rossi 3d6fcb845b feat(executor): add state-aware page-close warnings
Warn only when a closed page is stored in session state (for example state.page), include affected state key names in warning text, and preserve automatic fallback to another open page.

Also standardize skill guidance/examples on state.page, add integration coverage for warning and non-warning close paths, and simplify warning-scope bookkeeping by removing execution-id map state in favor of scope object tracking.
2026-02-20 14:40:05 +01:00
Tommy D. Rossi fdb19c5736 increase table cell contrast in light mode (muted opacity 0.35 -> 0.5) 2026-02-20 13:04:05 +01:00
Tommy D. Rossi a7ab6708ef fix code block bleed alignment and line numbers
- Fixed --ll-bleed to 44px (8px padding + 36px line-number width, border-box)
- Line numbers fixed width 36px (always fits 3 digits, no layout shift)
- Line number opacity increased from 0.15 to 0.3 in both light and dark mode
- Commented out code block background
2026-02-20 12:57:41 +01:00
Tommy D. Rossi acd63a9235 liveline: add Link component, OL, remove BackButton, dedent code blocks, spacing tweaks
- Add A (link) component with --ll-accent color, bright #58a6ff in dark mode
- Add OL (ordered list) component for numbered steps
- Remove BackButton from EditorialPage
- Use string-dedent for all CodeBlock strings, properly indented in source
- Getting started steps as OL with clickable Chrome Web Store link
- Star on GitHub link in intro paragraph
- Inline heading rule (flex + 1px line) replaces separate Divider
- Heading padding 24px top/bottom, article gap 32px
- Sidebar TOC item spacing increased to 5px
- Centered image captions
2026-02-20 12:53:21 +01:00
Tommy D. Rossi abd28162aa liveline: inline heading rule, restore diagram, increase spacing
- SectionHeading now renders as flex row with hairline rule extending
  to fill remaining width after the heading text (matching benji.org)
- Removed separate Divider from Section component
- Restored original diagram layout from before refactor
- Increased article gap to 32px, heading padding to 24px top/bottom
- Centered image captions
2026-02-20 12:43:06 +01:00
Tommy D. Rossi 984f41cfbe extract editorial components to markdown.tsx, simplify liveline to content-only
- New website/src/components/markdown.tsx with all reusable components:
  EditorialPage, TableOfContents, BackButton, P, Code, Caption, CodeBlock,
  ChartPlaceholder, Section, Divider, SectionHeading, List, Li, PropsTable
- liveline.tsx reduced from ~988 to ~370 lines, now pure content
- Renamed Paragraph->P, InlineCode->Code for brevity
- TOC accepts items/logo props for reuse across pages
- Centered image captions
- Divider with equal top/bottom padding
- Variable spacing CSS rules for code blocks, images, section dividers
2026-02-20 12:38:54 +01:00
Tommy D. Rossi 23da0767e9 fix diagram 2026-02-20 12:29:07 +01:00
Tommy D. Rossi 2cb144099a Update pnpm-lock.yaml 2026-02-20 12:26:03 +01:00
Tommy D. Rossi 4079b2ac84 Update package.json 2026-02-20 12:26:00 +01:00
Tommy D. Rossi d338dba8c0 Update globals.css 2026-02-20 12:25:55 +01:00
Tommy D. Rossi 7fe09ea35e liveline: JetBrainsMono Nerd Font Mono for code blocks, fix diagram alignment
- Add @font-face for JetBrainsMono Nerd Font Mono (nerd-fonts v3.3.0) with
  proper box-drawing glyph support for seamless Unicode diagram rendering
- Update --ll-font-code to use NF Mono as primary, fallback to JetBrains Mono/SF Mono
- Fix liveline-prism.css: use var(--ll-font-code) instead of hardcoded SF Mono
- Remove unused Google Fonts JetBrains Mono link from root.tsx
- Fix diagram: keep Unicode box chars for seamless lines, use ASCII < > v for
  arrows (◄ ► ▼ render at inconsistent widths), recount all columns
2026-02-20 12:25:32 +01:00
Tommy D. Rossi 8511d17ed7 liveline: match benji.org inline code style with ::before background pill
Inline code now uses a subtle rgba(0,0,0,0.04) background pill via a ::before
pseudo-element with absolute inset and 4px border-radius, matching
benji.org/liveline exactly. Dark mode uses rgba(255,255,255,0.08).
Moved styles from inline to CSS class .ll-inline-code.
2026-02-20 11:52:07 +01:00
Tommy D. Rossi 1fb714a247 liveline: bold playwriter logo in sidebar, remove header text, remove image border-radius
- Replace arrow + 'Index' link with bold 'playwriter' logo text in TOC sidebar
- Remove 'Playwriter' subtitle and '2025' year from page header, start with first paragraph
- Remove rounded-lg from chart placeholder images for sharp edges
2026-02-20 11:21:03 +01:00
Tommy D. Rossi a71cc88336 refactor: replace .dark CSS selectors with @variant dark for strategy-agnostic dark mode
Replace all hardcoded .dark class selectors with Tailwind v4's @variant dark
directive, which compiles to whatever strategy is configured in
@custom-variant dark. This means changing the dark mode strategy
(class, prefers-color-scheme, data-attribute, or combined) only requires
updating one line in globals.css — all dark mode variable overrides
and token styles follow automatically.

Changes:
- globals.css: update @custom-variant to (&:where(.dark, .dark *)) to
  include the .dark element itself with zero specificity, replace
  .dark {} block with @variant dark {}
- liveline.css: replace .dark .liveline-page {} with
  @variant dark { .liveline-page {} }
- liveline-prism.css: replace 20+ .dark .token.* rules with a single
  @variant dark {} block
2026-02-20 11:05:09 +01:00
Tommy D. Rossi d562047618 add bleed to code blocks and images on liveline page
Code blocks and chart placeholders now extend 36px beyond the 550px prose
column on each side via negative margins (.ll-bleed class). This aligns the
code text (after line numbers) flush with the prose left edge.

- --ll-bleed: 36px CSS variable (8px div padding + 28px line-number span)
- Responsive: bleed disabled below 650px viewport
- overflow-x-hidden on page wrapper prevents horizontal scroll
2026-02-20 11:00:01 +01:00
Tommy D. Rossi 4dad886f14 add dark mode to website using prefers-color-scheme + .dark class
Inline script in <head> applies .dark class on <html> based on OS preference
and listens for live changes. All liveline page colors now use CSS variables
with dark overrides in .dark .liveline-page block.

- liveline.css: new vars (--ll-text-muted, --ll-text-hover, --ll-divider,
  --ll-code-line-nr, --ll-btn-bg/shadow, --ll-fade-*) + full dark overrides
- liveline-prism.css: GitHub Dark syntax highlighting theme under .dark
- liveline.tsx: ~30 hardcoded rgba/hex colors replaced with CSS vars
- root.tsx: anti-FOUC script toggling .dark from prefers-color-scheme
2026-02-19 18:02:07 +01:00
Tommy D. Rossi 35c885b199 rewrite liveline page to Playwriter content, update skill docs, add OG image
liveline.tsx: replace Liveline chart library content with Playwriter product page.
Sections now cover getting started, architecture, snapshots, visual labels,
sessions, debugger/editor, network interception, screen recording, comparison
tables, remote access, and security.

skill.md: clarify page reuse rules (reusing about:blank is fine), fix download
path to /tmp instead of ./ for cross-platform safety.

Add og-errore-vs-effect.png for errore comparison page.
2026-02-19 17:43:23 +01:00
Tommy D. Rossi 5a3acd9cb8 refactor liveline: extract Section, List, Li components
Simplifies article content by extracting repeated patterns into
reusable components:
- Section: wraps Divider + SectionHeading + children
- List: styled ul with typography inline styles
- Li: styled li with correct padding

Article JSX now reads as clean declarative markup instead of
verbose inline-styled HTML.
2026-02-19 10:04:45 +01:00
Tommy D. Rossi a8481af89b add liveline page: recreation of benji.org/liveline editorial design
Recreates the benji.org/liveline page in the website folder using React,
Tailwind, and the same editorial design system. Charts are replaced with
static SVG placeholders.

Typography:
- Inter variable font from rsms.me (same source as next/font)
- font-weight 475 body, 560 headings, font-optical-sizing: auto
- 14px body, 20px line-height, -0.09px letter-spacing
- Near-black text rgb(17,17,17), 40% opacity secondary
- Display P3 accent colors with @supports fallback

Layout:
- 550px narrow content column, fixed TOC sidebar
- Stagger-in entrance animation with cascading delays
- Fixed header fade gradient (multi-stop white-to-transparent)
- Scroll-spy TOC highlighting via IntersectionObserver

Code blocks:
- Prism.js syntax highlighting with GitHub-light color palette
- Line numbers column with 20px right padding
- 12px / 18px font size

Props tables, dividers, captions, code blocks, bullet lists all
styled to match the original computed values.
2026-02-19 09:56:30 +01:00
Tommy D. Rossi 38098c6153 fix stale popup warnings leaking across executions on error path
Oracle review found that popupWarnings was only drained on the success
path. If execute() threw, warnings would leak into the next unrelated
call. Now drain in both success and catch paths.

Also guard indexOf returning -1 when popup isn't in context.pages() yet.
2026-02-18 23:13:23 +01:00
Tommy D. Rossi ea4c66b2f5 use page.on('popup') instead of page.opener() for popup detection
page.opener() produced false positives during CDP reconnection because
existing pages re-enumerated via context.pages().forEach would sometimes
have a non-null opener. page.on('popup') only fires for actual
window.open() and target=_blank interactions, so it's safe to attach
on both new and existing pages without false positives.
2026-02-18 23:11:21 +01:00
Tommy D. Rossi 03a70fb9fe warn agents when popup windows are detected during execution
When window.open() creates a popup, agents have no visibility into it
and can't control it via playwriter. This adds a [WARNING] line to the
executor output telling agents the popup page index, URL, and to repeat
the interaction without popups or navigate to the URL directly.

Detection uses page.opener() on newly created pages (context 'page'
event), not on existing pages during reconnection to avoid false
positives.
2026-02-18 22:58:27 +01:00
Tommy D. Rossi 17fd10b50f skill: fix contradictions, remove duplicates, consolidate advice
Fixes:
- Bug: page.screenshotWithAccessibilityLabels was called as method on page,
  fixed to standalone function call
- Removed duplicate 'debugging playwriter issues' section at end of file
  (identical to the detailed one earlier)
- Softened waitForTimeout rule: short waits (1-2s) now acknowledged as
  acceptable for non-deterministic events like popups/animations
- Fixed download example path from /tmp/ to ./
- Added note that bare 'page' in examples is for brevity, real automation
  should use state.myPage
- Consolidated diff behavior explanation to one place in snapshot section
  (was repeated 3 times with slight inconsistencies)
- Trimmed redundant 'prefer snapshots' advice to reference the dedicated
  'choosing between snapshot methods' section
- Consolidated cmd+click popup advice (was in both mistakes and common
  patterns with duplicate examples)
- Cross-referenced iframe approaches: frameLocator for locator chaining,
  contentFrame for Frame objects needed by snapshot()
- Clarified require is the only option in sandbox (ESM import unavailable)
2026-02-18 22:20:52 +01:00
Tommy D. Rossi 18284efd9f skill: add observe feedback loop and print page URL in every observe step
The observe step now has an inner loop — if the page isn't ready (still
loading, wrong URL, expected content missing), the agent loops back to
observe again instead of acting on stale state. The ASCII diagram shows
the 'not ready' branch looping back to observe.

Every observe step in the example now prints page.url() before the
snapshot so the agent always knows the current URL. This catches
redirects and unexpected navigation between actions.
2026-02-18 18:14:37 +01:00
Tommy D. Rossi 539aeaac91 rename accessibilitySnapshot to snapshot for shorter agent usage
The function is now exposed as `snapshot()` in the executor sandbox scope.
`accessibilitySnapshot` remains as a backward-compatible alias pointing to
the same function, so existing agents and saved commands continue to work.

Updated all code examples across skill.md, README, PLAYWRITER_AGENTS,
docs, tests, and the extension welcome page to use the shorter name.
2026-02-18 17:13:57 +01:00
Tommy D. Rossi b5c14cb68d add test proving viewport screenshot dimensions are correct without clip param
In connectOverCDP mode, Playwright already falls back to querying
window.innerWidth/innerHeight for viewport size (screenshotter.ts
_originalViewportSize). This test confirms the screenshot dimensions
match exactly with just scale:'css' and no manual clip, proving
the clip in screenshotWithAccessibilityLabels is redundant.

The test goes through the full extension CDP path:
Playwright → relay server → extension WS → chrome.debugger
2026-02-18 00:56:43 +01:00
Tommy D. Rossi 7ed17d264f skill: add computer use section mapping Anthropic/Claude extension actions to Playwright equivalents
Add a 'computer use' section to skill.md showing how Playwriter covers all
actions from the Anthropic computer_20250124 tool and the Claude Chrome
extension's custom computer tool, using Playwright APIs instead of
screenshot-based coordinate clicking.

Each subsection shows the declarative locator-based approach first (preferred)
with coordinate-based fallback for canvas/maps/custom widgets.

Also adds docs/claude-extension-tools.json with all 16 tool schemas extracted
from the Claude Chrome extension v1.0.39 (minified source) for reference.
2026-02-18 00:44:44 +01:00
Tommy D. Rossi 05700fa53b release: playwriter@0.0.63
Security hardening for privileged HTTP routes (/cli/*, /recording/*).

- Block cross-origin browser requests via Sec-Fetch-Site header validation (browsers always set this forbidden header; Node.js/curl clients don't send it, so they're unaffected)
- Reject POST requests without Content-Type: application/json to prevent the CORS simple-request bypass (text/plain POST skips CORS preflight entirely)
- Enforce token authentication on /cli/* and /recording/* when --token is set (remote access mode), matching the behavior documented in remote-access.md
- Update remote-access.md to clarify which routes require token auth
- Add security regression tests covering all attack vectors: Sec-Fetch-Site blocking, Content-Type enforcement, token validation, and Node.js client pass-through
2026-02-17 15:54:39 +01:00
Tommy D. Rossi 9008920c95 skill: add interaction feedback loop and reuse about:blank tabs
Add observe → act → observe feedback loop section with ASCII diagram
and Framer command palette example. Agents must take a snapshot after
every action to verify the result before proceeding.

Also change page creation pattern to reuse existing about:blank tabs
instead of always creating new ones, with a note to navigate immediately
in the same execute call to prevent concurrent agents from grabbing the
same tab.
2026-02-17 15:53:25 +01:00
Tommy D. Rossi 33996d511f playwriter skill self improvement: prefer snapshots over screenshots, add debugging patterns
Lessons from real debugging session where ~6 screenshot+image-agent roundtrips
wasted context when a single accessibility snapshot filter would have answered.

Changes:
- **checking page state**: snapshots are the default, screenshots only for visual/CSS
- **common mistakes**: added quote escaping in $'...' (#6), screenshot overuse warning (#7)
- **accessibility snapshots**: added JS filtering pattern for large snapshots
- **debugging web apps**: new section using getLatestLogs, DOM inspection via
  evaluate, and combined snapshot+logs patterns
2026-02-16 20:54:21 +01:00
Tommy D. Rossi 55be6ec840 fix: sanitize Buffer and long string output in CLI/MCP logging
Buffer instances (from screenshots, PDFs, responses) were dumping hundreds of
chars of hex bytes via util.inspect. Long strings nested in objects (base64,
HTML) also wasted context window space.

- Add Buffer.prototype[util.inspect.custom] in all entry points (cli, mcp,
  cdp-relay) so Buffers display as '<Buffer N bytes>' instead of hex dumps
- Add maxStringLength: 1000 to all util.inspect calls so strings inside
  inspected objects get capped (top-level strings are untouched, the existing
  10k char overall truncation handles those)
2026-02-16 20:03:36 +01:00
Tommy D. Rossi 44370833f7 feat: bundle playwriter version in extension, warn when CLI/MCP is outdated
The extension now reports which playwriter version it was built with via a
`?v=` query param on its WebSocket connection to the relay. The relay stores
this and exposes it in `/extension/status` and `/extensions/status` endpoints.

CLI and MCP compare the extension's bundled version against their own VERSION.
If the extension was built with a newer playwriter, a warning is shown:

  Playwriter 0.0.60 is outdated (extension requires 0.0.62).
  Run `npm install -g playwriter@latest` or update the playwriter package.

This is fully backward compatible:
- Old extensions without `?v=` get `playwriterVersion: null`, no warning
- No WS protocol changes (version is in URL query params)
- Warning fires once per executor/session lifetime

Flow:
  vite build reads playwriter/package.json → injects __PLAYWRITER_VERSION__
  → extension sends ?v=X.Y.Z on WS connect → relay stores in ExtensionInfo
  → /extension/status returns playwriterVersion → CLI/executor checks & warns
2026-02-16 19:42:58 +01:00
Morse 387149c649 docs: add Chrome launch commands to skill.md for when browser is closed
When the Playwriter extension can't connect because Chrome isn't running,
agents now have platform-specific commands (macOS, Linux, Windows) to start
Chrome from the CLI. Also documents the --allowlisted-extension-id and
--auto-accept-this-tab-capture flags for enabling automatic tab capture
for screen recording without manual extension clicks.

Closes #48
2026-02-16 14:44:12 +01:00
Tommy D. Rossi ce775c06f6 fix: hide frontmatter in remote-access doc from GitHub rendering 2026-02-16 11:32:12 +01:00
Tommy D. Rossi f61509a91f release: playwriter@0.0.62 2026-02-14 16:32:17 +01:00
Tommy D. Rossi fa68e33a78 feat: support HTTPS URLs in PLAYWRITER_HOST + remote access guide
PLAYWRITER_HOST now accepts full URLs like `https://x-tunnel.traforo.dev`
in addition to plain hostnames. Previously it always constructed
`http://${host}:19988` which broke when using traforo tunnels (HTTPS on
port 443).

Added `parseRelayHost()` utility that detects URL protocols and returns
correct HTTP/WebSocket base URLs. Updated all consumers:
- cli.ts: getServerUrl()
- mcp.ts: getLogServerUrl(), checkRemoteServer()
- executor.ts: checkExtensionStatus()
- utils.ts: getCdpUrl() (ws:// → wss:// for HTTPS hosts)

Plain hostnames still work as before (appends :19988).

Added docs/remote-access.md covering:
- Architecture: playwriter serve + traforo tunnel through Cloudflare
- Host and remote machine setup with env vars
- Use cases: remote Mac mini, user support, multi-machine, VM/devcontainer
- Security model: non-guessable URLs, token auth, localhost-only extension
  endpoint, no open ports, visible automation, instant revocation
2026-02-14 16:31:04 +01:00
Tommy D. Rossi 737133641f release: playwriter@0.0.61
Simplify Unix port killing by replacing shell pipelines with direct lsof -t and process.kill().
2026-02-14 00:08:41 +01:00
Tommy D. Rossi 744a9b913a fix: recover relay startup from EADDRINUSE 2026-02-13 15:42:43 +01:00
Tommy D. Rossi 8ffaa9333b Add GitHub Sponsors funding option
- Create .github/FUNDING.yml to enable Sponsor button in repo sidebar
- Add Support section to README with sponsor link

Closes #46
2026-02-11 20:36:05 +01:00
Tommy D. Rossi 674e7c73ad release: @xmorse/playwright-core@1.59.3, playwriter@0.0.59
Fix 'Cannot find module graceful-fs' error on clean npx playwriter installs.

@xmorse/playwright-core@1.59.3:
- Add missing runtime dependencies: graceful-fs, retry, signal-exit
- Fixes GitHub #45

playwriter@0.0.59:
- Update @xmorse/playwright-core to 1.59.3
2026-02-11 19:28:08 +01:00