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
This commit is contained in:
Tommy D. Rossi
2026-02-20 16:06:45 +01:00
parent b7f02ac9f4
commit b2ab69c236
3 changed files with 59 additions and 57 deletions
+28 -28
View File
@@ -63,7 +63,7 @@ export default function LivelinePage() {
<EditorialPage toc={tocItems} logo="playwriter"> <EditorialPage toc={tocItems} logo="playwriter">
<P> <P>
Playwriter lets you control your Chrome browser with the full Playwriter lets you <strong>control your Chrome browser</strong> with the full
Playwright API. A Chrome extension, a local relay, and a CLI. No new Playwright API. A Chrome extension, a local relay, and a CLI. No new
browser windows, no Chrome flags, no context bloat.{" "} browser windows, no Chrome flags, no context bloat.{" "}
<A href="https://github.com/remorses/playwriter">Star on GitHub</A>. <A href="https://github.com/remorses/playwriter">Star on GitHub</A>.
@@ -84,7 +84,7 @@ export default function LivelinePage() {
Every browser automation MCP I tried either spawns a new Chrome Every browser automation MCP I tried either spawns a new Chrome
instance or forces you into a limited set of predefined tools. Playwriter instance or forces you into a limited set of predefined tools. Playwriter
does neither. It connects to the browser you already have open, does neither. It connects to the browser you already have open,
exposes the full Playwright API through a single{" "} exposes the <strong>full Playwright API</strong> through a single{" "}
<Code>execute</Code> tool, and gets out of the way. <Code>execute</Code> tool, and gets out of the way.
One tool. Any Playwright code. No wrappers. One tool. Any Playwright code. No wrappers.
</P> </P>
@@ -92,7 +92,7 @@ export default function LivelinePage() {
<Section id="getting-started" title="Getting started"> <Section id="getting-started" title="Getting started">
<P> <P>
Three steps. Extension, icon click, then you&apos;re automating. <strong>Three steps.</strong> Extension, icon click, then you&apos;re automating.
</P> </P>
<OL> <OL>
@@ -110,7 +110,7 @@ export default function LivelinePage() {
`}</CodeBlock> `}</CodeBlock>
<P> <P>
The extension connects your browser to a local WebSocket relay on{" "} The extension connects your browser to a <strong>local WebSocket relay</strong> on{" "}
<Code>localhost:19988</Code>. The CLI sends Playwright <Code>localhost:19988</Code>. The CLI sends Playwright
code through the relay. No remote servers, no accounts, nothing code through the relay. No remote servers, no accounts, nothing
leaves your machine. leaves your machine.
@@ -135,8 +135,8 @@ export default function LivelinePage() {
The extension uses <Code>chrome.debugger</Code> to The extension uses <Code>chrome.debugger</Code> to
attach to tabs where you clicked the icon. It opens a WebSocket attach to tabs where you clicked the icon. It opens a WebSocket
connection to a local relay server. The CLI (or MCP, or your own connection to a local relay server. The CLI (or MCP, or your own
Playwright script) connects to the same relay. CDP commands flow Playwright script) connects to the same relay. <strong>CDP commands flow
through; the extension forwards them to Chrome and sends responses through</strong>; the extension forwards them to Chrome and sends responses
back. back.
</P> </P>
@@ -158,9 +158,9 @@ export default function LivelinePage() {
`}</CodeBlock> `}</CodeBlock>
<P> <P>
No Chrome restart required. No <Code>--remote-debugging-port</Code>{" "} <strong>No Chrome restart required.</strong> No <Code>--remote-debugging-port</Code>{" "}
flags. The extension handles the CDP attachment transparently, and flags. The extension handles the CDP attachment transparently, and
the relay multiplexes sessions so multiple agents or CLI instances the relay <strong>multiplexes sessions</strong> so multiple agents or CLI instances
can work with the same browser simultaneously. can work with the same browser simultaneously.
</P> </P>
@@ -187,9 +187,9 @@ export default function LivelinePage() {
`}</CodeBlock> `}</CodeBlock>
<P> <P>
Each line ends with a locator you can pass directly to{" "} Each line ends with a <strong>locator</strong> you can pass directly to{" "}
<Code>page.locator()</Code>. Subsequent calls return a <Code>page.locator()</Code>. Subsequent calls return a
diff, so you only see what changed. Use{" "} <strong> diff</strong>, so you only see what changed. Use{" "}
<Code>search</Code> to filter large pages. <Code>search</Code> to filter large pages.
</P> </P>
@@ -202,8 +202,8 @@ export default function LivelinePage() {
`}</CodeBlock> `}</CodeBlock>
<P> <P>
Snapshots are text. They cost a fraction of what screenshots cost in Snapshots are <strong>text</strong>. They cost a fraction of what screenshots cost in
tokens. Use them as your primary debugging tool. Only reach for tokens. Use them as your <strong>primary debugging tool</strong>. Only reach for
screenshots when spatial layout matters &mdash; grids, dashboards, maps. screenshots when spatial layout matters &mdash; grids, dashboards, maps.
</P> </P>
@@ -217,8 +217,8 @@ export default function LivelinePage() {
<P> <P>
For pages where spatial layout matters,{" "} For pages where spatial layout matters,{" "}
<Code>screenshotWithAccessibilityLabels</Code> overlays <Code>screenshotWithAccessibilityLabels</Code> overlays{" "}
Vimium-style labels on every interactive element. Take a screenshot, <strong>Vimium-style labels</strong> on every interactive element. Take a screenshot,
read the labels, click by reference. read the labels, click by reference.
</P> </P>
@@ -230,7 +230,7 @@ export default function LivelinePage() {
`}</CodeBlock> `}</CodeBlock>
<P> <P>
Labels are color-coded by element type: yellow for links, orange for Labels are <strong>color-coded by element type</strong>: yellow for links, orange for
buttons, coral for inputs, pink for checkboxes, peach for sliders, buttons, coral for inputs, pink for checkboxes, peach for sliders,
salmon for menus, amber for tabs. The ref system is shared with{" "} salmon for menus, amber for tabs. The ref system is shared with{" "}
<Code>snapshot()</Code>, so you can switch between text <Code>snapshot()</Code>, so you can switch between text
@@ -246,7 +246,7 @@ export default function LivelinePage() {
<Section id="sessions" title="Sessions"> <Section id="sessions" title="Sessions">
<P> <P>
Each session runs in an isolated sandbox with its own{" "} Each session runs in an <strong>isolated sandbox</strong> with its own{" "}
<Code>state</Code> object. Variables, pages, listeners <Code>state</Code> object. Variables, pages, listeners
persist between calls within a session. Different sessions get persist between calls within a session. Different sessions get
different state. Browser tabs are shared. different state. Browser tabs are shared.
@@ -265,7 +265,7 @@ export default function LivelinePage() {
`}</CodeBlock> `}</CodeBlock>
<P> <P>
Create your own page to avoid interference from other agents. Reuse Create your own page to <strong>avoid interference</strong> from other agents. Reuse
an existing <Code>about:blank</Code> tab or create a an existing <Code>about:blank</Code> tab or create a
fresh one, and store it in <Code>state</Code>. fresh one, and store it in <Code>state</Code>.
</P> </P>
@@ -282,7 +282,7 @@ export default function LivelinePage() {
<Section id="debugger-and-editor" title="Debugger & editor"> <Section id="debugger-and-editor" title="Debugger & editor">
<P> <P>
Full Chrome DevTools Protocol access. Set breakpoints, step through <strong>Full Chrome DevTools Protocol access.</strong> Set breakpoints, step through
code, inspect variables at runtime. Live-edit page scripts and CSS code, inspect variables at runtime. Live-edit page scripts and CSS
without reloading. without reloading.
</P> </P>
@@ -299,7 +299,7 @@ export default function LivelinePage() {
`}</CodeBlock> `}</CodeBlock>
<P> <P>
Edits are in-memory and persist until the page reloads. Useful for Edits are <strong>in-memory</strong> and persist until the page reloads. Useful for
toggling debug flags, patching broken code, or testing quick fixes toggling debug flags, patching broken code, or testing quick fixes
without touching source files. The editor also supports{" "} without touching source files. The editor also supports{" "}
<Code>grep</Code> across all loaded scripts. <Code>grep</Code> across all loaded scripts.
@@ -314,7 +314,7 @@ export default function LivelinePage() {
<Section id="network-interception" title="Network interception"> <Section id="network-interception" title="Network interception">
<P> <P>
Intercept requests and responses to reverse-engineer APIs, scrape <strong>Intercept requests and responses</strong> to reverse-engineer APIs, scrape
data, or debug network issues. Store captured data in{" "} data, or debug network issues. Store captured data in{" "}
<Code>state</Code> and analyze across calls. <Code>state</Code> and analyze across calls.
</P> </P>
@@ -332,7 +332,7 @@ export default function LivelinePage() {
`}</CodeBlock> `}</CodeBlock>
<P> <P>
This is faster than scrolling through DOM. Capture the real API This is <strong>faster than scrolling through DOM</strong>. Capture the real API
calls, inspect their schemas, and replay them with different calls, inspect their schemas, and replay them with different
parameters. Works for pagination, authenticated endpoints, and parameters. Works for pagination, authenticated endpoints, and
anything behind JavaScript rendering. anything behind JavaScript rendering.
@@ -343,9 +343,9 @@ export default function LivelinePage() {
<Section id="screen-recording" title="Screen recording"> <Section id="screen-recording" title="Screen recording">
<P> <P>
Record the active tab as video using{" "} <strong>Record the active tab as video</strong> using{" "}
<Code>chrome.tabCapture</Code>. The recording runs in <Code>chrome.tabCapture</Code>. The recording runs in
the extension context, so it survives page navigation. Video is saved the extension context, so it <strong>survives page navigation</strong>. Video is saved
as MP4. as MP4.
</P> </P>
@@ -363,7 +363,7 @@ export default function LivelinePage() {
<P> <P>
Unlike <Code>getDisplayMedia</Code>, this approach Unlike <Code>getDisplayMedia</Code>, this approach
persists across navigations because the extension holds the{" "} <strong> persists across navigations</strong> because the extension holds the{" "}
<Code>MediaRecorder</Code>, not the page. You can also <Code>MediaRecorder</Code>, not the page. You can also
check recording status with <Code>isRecording</Code> or check recording status with <Code>isRecording</Code> or
cancel without saving with <Code>cancelRecording</Code>. cancel without saving with <Code>cancelRecording</Code>.
@@ -424,11 +424,11 @@ export default function LivelinePage() {
<Section id="remote-access" title="Remote access"> <Section id="remote-access" title="Remote access">
<P> <P>
Control Chrome on any machine from anywhere over the internet. Control Chrome on <strong>any machine from anywhere</strong> over the internet.
The relay runs on the host alongside Chrome. The relay runs on the host alongside Chrome.
A{" "} A{" "}
<A href="https://traforo.dev">traforo</A>{" "} <A href="https://traforo.dev">traforo</A>{" "}
tunnel exposes it through Cloudflare, giving you a secure public URL. tunnel exposes it through Cloudflare, giving you a <strong>secure public URL</strong>.
No VPN, no firewall rules, no port forwarding. No VPN, no firewall rules, no port forwarding.
</P> </P>
@@ -443,7 +443,7 @@ export default function LivelinePage() {
`}</CodeBlock> `}</CodeBlock>
<P> <P>
Also works on a LAN without tunnels &mdash; just set{" "} Also works on a <strong>LAN without tunnels</strong> &mdash; just set{" "}
<Code>PLAYWRITER_HOST=192.168.1.10</Code>. Works for MCP <Code>PLAYWRITER_HOST=192.168.1.10</Code>. Works for MCP
too &mdash; set <Code>PLAYWRITER_HOST</Code> and{" "} too &mdash; set <Code>PLAYWRITER_HOST</Code> and{" "}
<Code>PLAYWRITER_TOKEN</Code> in your MCP client env config. <Code>PLAYWRITER_TOKEN</Code> in your MCP client env config.
@@ -456,7 +456,7 @@ export default function LivelinePage() {
<Section id="security" title="Security"> <Section id="security" title="Security">
<P> <P>
Playwriter is local by default. The relay runs on{" "} Playwriter is <strong>local by default</strong>. The relay runs on{" "}
<Code>localhost:19988</Code> and only accepts connections <Code>localhost:19988</Code> and only accepts connections
from the extension. There&apos;s no remote server, no account, no from the extension. There&apos;s no remote server, no account, no
telemetry. telemetry.
+29 -27
View File
@@ -1,25 +1,27 @@
/* /*
* Prism.js light theme matching benji.org's GitHub-style syntax highlighting. * Prism.js light theme — more saturated, brighter variant of GitHub Light.
* *
* Color palette extracted from the original: * Color palette:
* - Keywords (import, function, return): #CF222E (red) * - Keywords (import, function, return): #d1242f (vivid red)
* - Strings: #0A3069 (dark blue) * - Strings: #0550ae (rich blue)
* - Functions/components: #8250DF (purple) * - Functions/components: #7c3aed (vivid purple)
* - Parameters/properties: #953800 (orange-brown) * - Parameters/properties: #b45309 (warm amber)
* - HTML tags: #116329 (green) * - HTML tags: #16a34a (bright green)
* - Attributes/numbers: #0550AE (blue) * - Attributes/numbers: #2563eb (bright blue)
* - Punctuation/text: #1F2328 (near-black) * - Punctuation/text: #1e293b (slate)
*/ */
/* Base code style - override Prism defaults */ /* Base code style - override Prism defaults */
code[class*="language-"], code[class*="language-"],
pre[class*="language-"] { pre[class*="language-"] {
color: #1f2328; color: #1e293b;
background: none; background: none;
text-shadow: none; text-shadow: none;
font-family: var(--ll-font-code, "SF Mono", "SFMono-Regular", "Consolas", font-family: var(--ll-font-code, "SF Mono", "SFMono-Regular", "Consolas",
"Liberation Mono", Menlo, Courier, monospace); "Liberation Mono", Menlo, Courier, monospace);
font-size: 12px; font-size: 12px;
font-weight: 500;
letter-spacing: 0.02em;
line-height: 18px; line-height: 18px;
text-align: left; text-align: left;
white-space: pre; white-space: pre;
@@ -35,64 +37,64 @@ pre[class*="language-"] {
.token.module, .token.module,
.token.imports, .token.imports,
.token.control-flow { .token.control-flow {
color: #cf222e; color: #d1242f;
} }
/* Strings and template literals */ /* Strings and template literals */
.token.string, .token.string,
.token.template-string, .token.template-string,
.token.attr-value { .token.attr-value {
color: #0a3069; color: #0550ae;
} }
/* Function names */ /* Function names */
.token.function, .token.function,
.token.class-name { .token.class-name {
color: #8250df; color: #7c3aed;
} }
/* Object properties, parameters, variables in destructuring */ /* Object properties, parameters, variables in destructuring */
.token.property, .token.property,
.token.parameter { .token.parameter {
color: #953800; color: #b45309;
} }
/* HTML/JSX tag names */ /* HTML/JSX tag names */
.token.tag .token.tag { .token.tag .token.tag {
color: #116329; color: #16a34a;
} }
/* Also color component names (PascalCase tags) in JSX */ /* Also color component names (PascalCase tags) in JSX */
.token.tag .token.class-name { .token.tag .token.class-name {
color: #116329; color: #16a34a;
} }
/* Attributes in JSX/HTML */ /* Attributes in JSX/HTML */
.token.tag .token.attr-name, .token.tag .token.attr-name,
.token.attr-name { .token.attr-name {
color: #0550ae; color: #2563eb;
} }
/* Numbers */ /* Numbers */
.token.number { .token.number {
color: #0550ae; color: #2563eb;
} }
/* Operators: =, ===, =>, +, - */ /* Operators: =, ===, =>, +, - */
.token.operator { .token.operator {
color: #cf222e; color: #d1242f;
} }
/* Punctuation: brackets, parens, commas, semicolons */ /* Punctuation: brackets, parens, commas, semicolons */
.token.punctuation { .token.punctuation {
color: #1f2328; color: #1e293b;
} }
/* Booleans, null, undefined */ /* Booleans, null, undefined */
.token.boolean, .token.boolean,
.token.constant, .token.constant,
.token.builtin { .token.builtin {
color: #0550ae; color: #2563eb;
} }
/* Comments */ /* Comments */
@@ -100,33 +102,33 @@ pre[class*="language-"] {
.token.prolog, .token.prolog,
.token.doctype, .token.doctype,
.token.cdata { .token.cdata {
color: #6e7781; color: #6b7280;
font-style: italic; font-style: italic;
} }
/* JSX specific: tag punctuation < > / */ /* JSX specific: tag punctuation < > / */
.token.tag .token.punctuation { .token.tag .token.punctuation {
color: #1f2328; color: #1e293b;
} }
/* Spread operator, rest */ /* Spread operator, rest */
.token.spread { .token.spread {
color: #cf222e; color: #d1242f;
} }
/* Plain text inside tags */ /* Plain text inside tags */
.token.plain-text { .token.plain-text {
color: #1f2328; color: #1e293b;
} }
/* Regex */ /* Regex */
.token.regex { .token.regex {
color: #0a3069; color: #0550ae;
} }
/* Shell/bash specific */ /* Shell/bash specific */
.language-bash .token.function { .language-bash .token.function {
color: #0550ae; color: #2563eb;
} }
/* No text shadow on any token */ /* No text shadow on any token */
+2 -2
View File
@@ -244,9 +244,9 @@
display: inline-block; display: inline-block;
font-family: var(--ll-font-code); font-family: var(--ll-font-code);
font-size: 12.6px; font-size: 12.6px;
font-weight: 460; font-weight: 500;
line-height: 12.6px; line-height: 12.6px;
letter-spacing: -0.09px; letter-spacing: 0.02em;
padding: 1.6px 3.2px; padding: 1.6px 3.2px;
color: rgba(0, 0, 0, 0.75); color: rgba(0, 0, 0, 0.75);
} }