rpc-agent 0.0.0-stage → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +103 -0
- package/LICENSE +21 -0
- package/NOTICE +16 -0
- package/README.md +302 -2
- package/assets/bezels/imac.svg +63 -0
- package/assets/bezels/ipad.svg +27 -0
- package/assets/bezels/iphone-11-pro.svg +35 -0
- package/assets/bezels/iphone-12-mini.svg +26 -0
- package/assets/bezels/iphone-12-pro-max.svg +26 -0
- package/assets/bezels/iphone-17-pro.svg +172 -0
- package/assets/bezels/iphone-se.svg +37 -0
- package/assets/bezels/laptop.svg +25 -0
- package/assets/bezels/macbook-air.svg +235 -0
- package/assets/bezels/macbook-pro-13.svg +63 -0
- package/assets/bezels/macbook-pro-14.svg +115 -0
- package/assets/bezels/macbook-pro.svg +32 -0
- package/assets/bezels/macbook.svg +25 -0
- package/assets/bezels/monitor.svg +57 -0
- package/assets/bezels/phone-classic.svg +17 -0
- package/assets/bezels/phone-home.svg +12 -0
- package/assets/bezels/phone-island.svg +130 -0
- package/assets/bezels/phone-notch.svg +26 -0
- package/assets/bezels/surface-laptop.svg +84 -0
- package/assets/bezels/tablet.svg +25 -0
- package/assets/bezels/windows-laptop.svg +84 -0
- package/dist/args.js +189 -0
- package/dist/bezel.js +74 -0
- package/dist/browser.js +80 -0
- package/dist/capture.js +241 -0
- package/dist/cli.js +175 -0
- package/dist/composite.js +115 -0
- package/dist/devices.js +407 -0
- package/dist/errors.js +115 -0
- package/dist/help.js +110 -0
- package/dist/mcp.js +245 -0
- package/dist/options.js +51 -0
- package/dist/png.js +183 -0
- package/dist/slices.js +59 -0
- package/dist/term.js +46 -0
- package/dist/ui.js +488 -0
- package/package.json +67 -4
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 0.3.1
|
|
4
|
+
|
|
5
|
+
Published to npm as `rpc-agent`.
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- Install with `npx rpc-agent …` or `npm i -g rpc-agent`. MCP setup for
|
|
10
|
+
Claude Code is `claude mcp add --scope user rpc -- npx -y rpc-agent mcp`;
|
|
11
|
+
Cursor uses `"command": "npx", "args": ["-y", "rpc-agent", "mcp"]`.
|
|
12
|
+
- Package metadata (repository, homepage, bugs, keywords, author) and a
|
|
13
|
+
`prepublishOnly` check that typechecks, builds and runs the tests.
|
|
14
|
+
|
|
15
|
+
### Changed
|
|
16
|
+
|
|
17
|
+
- The missing-Chromium message now says `npx rpc-agent install` (or
|
|
18
|
+
`rpc install`) and names the Playwright version, instead of pointing at
|
|
19
|
+
`npx playwright install chromium` inside the package folder, which under
|
|
20
|
+
npx is a cache directory and could pull a different Playwright.
|
|
21
|
+
- `rpc install` run through npx no longer shows Playwright's "install your
|
|
22
|
+
project's dependencies" warning box, which didn't apply.
|
|
23
|
+
- `rpc install` downloads only Chromium's headless shell (`--only-shell`),
|
|
24
|
+
which is all rpc launches: about 210 MB on disk instead of about 580 MB.
|
|
25
|
+
- Requires Node 20.12 or newer (what `@clack/prompts` needs).
|
|
26
|
+
- Chromium is still never downloaded on install: run `rpc install` once.
|
|
27
|
+
|
|
28
|
+
## 0.3.0
|
|
29
|
+
|
|
30
|
+
A terminal UI modelled on the `skills` CLI (skills.sh). Nothing changes for
|
|
31
|
+
agents, scripts or CI.
|
|
32
|
+
|
|
33
|
+
### Added
|
|
34
|
+
|
|
35
|
+
- `rpc` with no arguments, in a terminal, is an interactive capture: URL
|
|
36
|
+
(defaults to a running dev server on localhost), a grouped device picker,
|
|
37
|
+
bezels / full page / dark mode / reduced motion, a summary and a confirm.
|
|
38
|
+
It ends with the equivalent `rpc shot` command.
|
|
39
|
+
- `rpc shot` in a terminal: `RPC` banner, a capture summary, a spinner per
|
|
40
|
+
device that resolves to status and time, a results table (status, time,
|
|
41
|
+
console errors), the files written with pixel and file sizes, failures
|
|
42
|
+
grouped with their hint, and `Done! Open with: open .rpc-shots`.
|
|
43
|
+
- `--open` opens the output folder when the capture finishes.
|
|
44
|
+
- `rpc devices` in a terminal: aligned, coloured by category, with each
|
|
45
|
+
device's aliases. `rpc doctor` in a terminal: a checklist with the fix in
|
|
46
|
+
a box.
|
|
47
|
+
- Per-command help: `rpc help shot`, `rpc shot --help` (also devices,
|
|
48
|
+
doctor, install, mcp). `rpc --help` in a terminal has sections and
|
|
49
|
+
examples.
|
|
50
|
+
- `docs/cli-design.md`: what rpc borrows from the `skills` CLI and when the
|
|
51
|
+
rich output is used.
|
|
52
|
+
|
|
53
|
+
### Unchanged
|
|
54
|
+
|
|
55
|
+
- Output to pipes, files and CI (`CI` set, `TERM=dumb`) is the 0.2 output.
|
|
56
|
+
`--json` output, exit codes and the MCP server are untouched; `rpc mcp`
|
|
57
|
+
and `--json` don't load the UI code. `NO_COLOR` turns colour off and
|
|
58
|
+
`FORCE_COLOR` turns it on for the plain output.
|
|
59
|
+
|
|
60
|
+
### Dependencies
|
|
61
|
+
|
|
62
|
+
- `@clack/prompts` and `picocolors`.
|
|
63
|
+
|
|
64
|
+
## 0.2.0
|
|
65
|
+
|
|
66
|
+
From the first real use: an agent reviewing a deployed site on iphone-15,
|
|
67
|
+
ipad and desktop-1440 with bezels and full page.
|
|
68
|
+
|
|
69
|
+
### Added
|
|
70
|
+
|
|
71
|
+
- Full pages of any height. Pages taller than Chromium's 16,384 px capture
|
|
72
|
+
limit are taken as clipped full-page segments and stitched in Node (no
|
|
73
|
+
native dependencies). Sticky headers and fixed elements appear once. New
|
|
74
|
+
`maxHeight` / `--max-height` cap (60,000 CSS px), reported as `clipped`,
|
|
75
|
+
with `capturedHeight` and `segments` in the result.
|
|
76
|
+
- Full-page review in one MCP call. With `fullPage`, `screenshot` returns the
|
|
77
|
+
framed first screen and then the whole page as labelled, viewport-tall JPEG
|
|
78
|
+
slices (`iphone-15 · slice 2/7 · y=852–1704 css px`). New params
|
|
79
|
+
`maxSlices` (10), `saveSlices` and `sliceWidth` (768). When slices are cut,
|
|
80
|
+
the result says which range was skipped, and every slice is saved to disk
|
|
81
|
+
with its path listed. CLI: `--slices`, `--slice-width`.
|
|
82
|
+
- Actionable errors. Navigation failures come back per device as `error`,
|
|
83
|
+
`code` (`ERR_NAME_NOT_RESOLVED`, `TIMEOUT`, ...) and `hint`, covering
|
|
84
|
+
sandbox / network allowlists, dev servers not running, proxies, TLS and
|
|
85
|
+
timeouts. MCP results lead with the failures in plain text.
|
|
86
|
+
- `reducedMotion` / `--reduced-motion` emulates
|
|
87
|
+
`prefers-reduced-motion: reduce`.
|
|
88
|
+
- Missing-browser check. If Playwright's Chromium isn't installed, the CLI and
|
|
89
|
+
the MCP tool say so with the fix (`npx playwright install chromium`, or
|
|
90
|
+
`rpc install`) instead of Playwright's raw error; the MCP server keeps
|
|
91
|
+
running. New `rpc doctor` and `rpc install` commands.
|
|
92
|
+
|
|
93
|
+
### Changed
|
|
94
|
+
|
|
95
|
+
- The warm-up scroll covers the whole capped height (up to 100 steps) rather
|
|
96
|
+
than stopping at 30,000 px.
|
|
97
|
+
- `pnpm smoke:mcp` takes `--full-page`, `--devices`, `--max-slices`, `--out`.
|
|
98
|
+
|
|
99
|
+
## 0.1.0
|
|
100
|
+
|
|
101
|
+
First version: CLI and stdio MCP server, 49 devices and bezels from
|
|
102
|
+
Responsive Point Check, Playwright Chromium capture, bezel compositing in a
|
|
103
|
+
Playwright page.
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Akintola Tope
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/NOTICE
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
rpc-agent
|
|
2
|
+
Derived from responsive-point-check (https://github.com/akintola4/responsive-point-check),
|
|
3
|
+
MIT License, Copyright (c) 2026 Akintola Tope.
|
|
4
|
+
|
|
5
|
+
Device catalog (src/devices.ts) and bezel layout logic (src/bezel.ts) are ported
|
|
6
|
+
from lib/devices.ts and lib/bezel-asset.ts in that repository.
|
|
7
|
+
|
|
8
|
+
Bezel artwork (assets/bezels/*.svg) is copied unchanged from public/bezels/ in
|
|
9
|
+
that repository and distributed under its MIT license. The SVGs carry no author
|
|
10
|
+
or license metadata of their own; their element ids indicate Figma exports, but
|
|
11
|
+
the original Figma source is not recorded in the upstream repo. Confirm the
|
|
12
|
+
artwork's origin before any public release.
|
|
13
|
+
|
|
14
|
+
The artwork depicts hardware made by Apple, Google, Samsung and Microsoft.
|
|
15
|
+
Device names and product designs are trademarks of their respective owners.
|
|
16
|
+
This project is not affiliated with or endorsed by any of them.
|
package/README.md
CHANGED
|
@@ -1,3 +1,303 @@
|
|
|
1
|
-
#
|
|
1
|
+
# rpc-agent
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
<picture>
|
|
4
|
+
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/akintola4/rpc-agent/main/docs/media/hero-dark.png">
|
|
5
|
+
<img alt="A site captured by rpc on an iPhone 15, an iPad Air 11 and a 1440 px desktop, each framed in its device bezel" src="https://raw.githubusercontent.com/akintola4/rpc-agent/main/docs/media/hero-light.png">
|
|
6
|
+
</picture>
|
|
7
|
+
|
|
8
|
+
Screenshot a URL at real device viewports, optionally framed in a device
|
|
9
|
+
bezel, so an AI coding agent can look at the UI it just built. It's a CLI and
|
|
10
|
+
an MCP server in one package, with Playwright (Chromium) doing the capture.
|
|
11
|
+
|
|
12
|
+
The device catalog (49 phones, tablets, laptops and monitors) and the SVG
|
|
13
|
+
bezels come from the [Responsive Point Check](https://github.com/akintola4/responsive-point-check)
|
|
14
|
+
Chrome extension. See `NOTICE` for where the artwork comes from.
|
|
15
|
+
|
|
16
|
+
## Install
|
|
17
|
+
|
|
18
|
+
Requires Node 20.12 or newer. Run it without installing:
|
|
19
|
+
|
|
20
|
+
```sh
|
|
21
|
+
npx rpc-agent install # first run: download headless Chromium (~210 MB on disk)
|
|
22
|
+
npx rpc-agent shot localhost:3000 -d iphone-15,desktop-1440 --bezels
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Or install it globally to get the `rpc` command:
|
|
26
|
+
|
|
27
|
+
```sh
|
|
28
|
+
npm i -g rpc-agent
|
|
29
|
+
rpc install # first run: download Chromium
|
|
30
|
+
rpc doctor # checks Chromium is installed and launches
|
|
31
|
+
rpc shot https://example.com --bezels
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Chromium is not downloaded when the package installs. `rpc install` (or
|
|
35
|
+
`npx rpc-agent install`) fetches it with rpc's own Playwright version, so
|
|
36
|
+
the browser always matches the one rpc launches. It installs only
|
|
37
|
+
Chromium's headless shell (plus Playwright's small ffmpeg), not the full
|
|
38
|
+
Chrome for Testing build, since rpc never opens a visible window. Until you run it, every
|
|
39
|
+
command says Chromium is missing and prints that command, instead of
|
|
40
|
+
failing with Playwright's own error. Browsers go to Playwright's usual
|
|
41
|
+
cache, so other Playwright projects on the same version share them.
|
|
42
|
+
|
|
43
|
+
### From source
|
|
44
|
+
|
|
45
|
+
```sh
|
|
46
|
+
git clone https://github.com/akintola4/rpc-agent.git
|
|
47
|
+
cd rpc-agent
|
|
48
|
+
pnpm install && pnpm build
|
|
49
|
+
node dist/cli.js install
|
|
50
|
+
pnpm link --global # optional: puts this build's `rpc` on your PATH
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Without the link, run `node /absolute/path/to/rpc-agent/dist/cli.js` where
|
|
54
|
+
these docs say `rpc`, or `pnpm rpc` from inside the repo.
|
|
55
|
+
|
|
56
|
+
## CLI
|
|
57
|
+
|
|
58
|
+

|
|
59
|
+
|
|
60
|
+
```sh
|
|
61
|
+
rpc # interactive: pick a URL, devices and options
|
|
62
|
+
rpc shot <url> [options]
|
|
63
|
+
rpc devices [--json]
|
|
64
|
+
rpc doctor [--json] # is Chromium installed, and does it launch?
|
|
65
|
+
rpc install # download Chromium with rpc's own Playwright version
|
|
66
|
+
rpc mcp
|
|
67
|
+
rpc help <command> # options and examples for one command
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
Run `rpc` with no arguments in a terminal and it asks for the URL
|
|
71
|
+
(defaulting to a dev server on localhost:3000, 5173, 4321 or 8080 if one is
|
|
72
|
+
running), lets you tick devices from a grouped list (iPhone 15 Pro, iPad Air
|
|
73
|
+
11" and Desktop 1440 are preselected) and pick bezels, full page, dark mode
|
|
74
|
+
or reduced motion. It shows a summary, asks before capturing, and prints the
|
|
75
|
+
equivalent `rpc shot` command at the end so you can re-run it.
|
|
76
|
+
|
|
77
|
+
`rpc shot` in a terminal shows each device's progress, a results table and
|
|
78
|
+
the files it wrote:
|
|
79
|
+
|
|
80
|
+
<img alt="rpc shot in a terminal: a capture summary, one line per device with HTTP status and time, a results table, and the list of files written" src="https://raw.githubusercontent.com/akintola4/rpc-agent/main/docs/media/terminal-shot.png" width="720">
|
|
81
|
+
|
|
82
|
+
| Option | Meaning |
|
|
83
|
+
| --- | --- |
|
|
84
|
+
| `-d, --devices <ids>` | Comma-separated device ids or aliases. Default `iphone-15-pro,desktop-1440` |
|
|
85
|
+
| `-b, --bezels` | Also write a copy framed in the device bezel |
|
|
86
|
+
| `-f, --full-page` | Capture the full scroll height, however tall (up to `--max-height`) |
|
|
87
|
+
| `--slices` | With `--full-page`, also write viewport-tall JPEG review slices |
|
|
88
|
+
| `--slice-width <px>` | Maximum slice width. Default 768 |
|
|
89
|
+
| `--max-height <px>` | Full-page cap in CSS px. Default 60000 |
|
|
90
|
+
| `--reduced-motion` | Emulate `prefers-reduced-motion: reduce` |
|
|
91
|
+
| `-o, --out <dir>` | Output directory. Default `./.rpc-shots` |
|
|
92
|
+
| `--wait-for <selector>` | Wait for a visible element before capturing |
|
|
93
|
+
| `--wait <ms>` | Extra settle delay after load |
|
|
94
|
+
| `--color-scheme <s>` | `light`, `dark` or `no-preference` |
|
|
95
|
+
| `--timeout <ms>` | Navigation timeout. Default 30000 |
|
|
96
|
+
| `--no-emulate` | Viewport and DPR only: no mobile user agent or touch |
|
|
97
|
+
| `--json` | Print the result as JSON |
|
|
98
|
+
| `--open` | Open the output folder when done (`open`, `xdg-open` or `explorer`) |
|
|
99
|
+
|
|
100
|
+
The URL can be a full URL, a bare local host (`localhost:3000` becomes
|
|
101
|
+
`http://`), a bare domain (`example.com` becomes `https://`) or a path to a
|
|
102
|
+
local `.html` file.
|
|
103
|
+
|
|
104
|
+
```sh
|
|
105
|
+
rpc shot localhost:3000 -d iphone-15,ipad,desktop-1440 --bezels
|
|
106
|
+
rpc shot https://example.com/pricing --full-page --slices --color-scheme dark
|
|
107
|
+
rpc shot localhost:5173 -d pixel --wait-for '[data-ready]' --json
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
Output files are named `<host>[-<path>]-<device>.png`, with `-framed.png`
|
|
111
|
+
for bezel copies and `-slice-NN.jpg` for slices, for example
|
|
112
|
+
`.rpc-shots/localhost-3000-iphone-15.png`. Re-running overwrites them, so the
|
|
113
|
+
paths stay the same between runs.
|
|
114
|
+
|
|
115
|
+
Aliases: `iphone`, `mobile`, `phone` (iphone-15-pro), `android`, `pixel`
|
|
116
|
+
(pixel-8), `galaxy` (galaxy-s24), `ipad`, `tablet` (ipad-air-11), `macbook`
|
|
117
|
+
(macbook-air-13), `laptop` (laptop-1280), `desktop` (desktop-1440), `imac`
|
|
118
|
+
(imac-24). Run `rpc devices` for the full list.
|
|
119
|
+
|
|
120
|
+
### What a capture does
|
|
121
|
+
|
|
122
|
+
Each device gets a fresh browser context with its CSS viewport, device pixel
|
|
123
|
+
ratio and, for phones and tablets, a mobile user agent plus touch. The page
|
|
124
|
+
loads, then rpc waits for network idle (up to 10 s, so dev servers with HMR
|
|
125
|
+
sockets don't hang it), web fonts and pending images. CSS animations,
|
|
126
|
+
transitions and Web Animations are finished before the shot.
|
|
127
|
+
|
|
128
|
+
With `--full-page`, rpc first scrolls through the page one viewport at a time
|
|
129
|
+
so lazy images and IntersectionObserver content load, then scrolls back to
|
|
130
|
+
the top. A page that fits in one Chromium capture (16,384 device px) is taken
|
|
131
|
+
in one pass. A taller one is taken as clipped segments of about 8,000 device
|
|
132
|
+
px and stitched into one PNG in Node, with no height limit apart from
|
|
133
|
+
`--max-height` (60,000 CSS px by default; taller pages are cut there and
|
|
134
|
+
marked `clipped`). Both paths render the page as if the viewport were the
|
|
135
|
+
whole document, so sticky headers and fixed elements appear once, at the top,
|
|
136
|
+
and `100vh` sections keep their real height.
|
|
137
|
+
|
|
138
|
+
Bezels frame the above-the-fold viewport. With `--bezels --full-page` you get
|
|
139
|
+
both: the full page raw, and the first screen framed.
|
|
140
|
+
|
|
141
|
+
### Terminal, pipes and CI
|
|
142
|
+
|
|
143
|
+
The banner, spinners, prompts and boxes only appear when stdout is an
|
|
144
|
+
interactive terminal. When output goes to a pipe or a file, when `CI` is
|
|
145
|
+
set, when `TERM=dumb`, and always with `--json`, rpc prints the same plain
|
|
146
|
+
lines as 0.2 (`ok …`, `x …` plus `hint:`), so agents and scripts that read
|
|
147
|
+
them see no change. `NO_COLOR` turns colour off; `FORCE_COLOR=1` adds colour
|
|
148
|
+
to the plain lines. `rpc mcp` never prints anything but MCP messages.
|
|
149
|
+
|
|
150
|
+
### When a capture fails
|
|
151
|
+
|
|
152
|
+
Each device fails on its own, with an `error`, a `code` and usually a `hint`.
|
|
153
|
+
In a terminal, devices that fail the same way share one hint:
|
|
154
|
+
|
|
155
|
+
<img alt="rpc shot against a host that doesn't resolve: both devices fail with ERR_NAME_NOT_RESOLVED and one hint explains what to check" src="https://raw.githubusercontent.com/akintola4/rpc-agent/main/docs/media/terminal-error.png" width="720">
|
|
156
|
+
|
|
157
|
+
Plain output (pipes, agents, CI):
|
|
158
|
+
|
|
159
|
+
```
|
|
160
|
+
x iphone-15 (393x852 @3x): Could not resolve host example.dev (net::ERR_NAME_NOT_RESOLVED)
|
|
161
|
+
hint: Check the URL for typos. If the host works in a normal browser, this process may be
|
|
162
|
+
blocked by a sandbox or network allowlist (e.g. the Claude Code sandbox: add the domain to
|
|
163
|
+
the allowed hosts, or run outside the sandbox). ...
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
Covered: DNS failures, refused connections (on localhost: "nothing is
|
|
167
|
+
listening on port N"), proxy, tunnel and offline errors, TLS errors (https
|
|
168
|
+
against a plain-http dev server), missing files, redirect loops, navigation
|
|
169
|
+
and `--wait-for` timeouts.
|
|
170
|
+
|
|
171
|
+
## MCP server
|
|
172
|
+
|
|
173
|
+
`rpc mcp` runs an MCP server on stdio with two tools.
|
|
174
|
+
|
|
175
|
+
### `screenshot`
|
|
176
|
+
|
|
177
|
+
| Param | Default | |
|
|
178
|
+
| --- | --- | --- |
|
|
179
|
+
| `url` | required | http(s), file, bare host or local path |
|
|
180
|
+
| `devices` | `["iphone-15-pro", "desktop-1440"]` | ids or aliases |
|
|
181
|
+
| `bezels` | false | framed copy of the first screen |
|
|
182
|
+
| `fullPage` | false | whole page, stitched past 16,384 px |
|
|
183
|
+
| `maxSlices` | 10 | full page: slices returned inline per device |
|
|
184
|
+
| `saveSlices` | auto | full page: `true` always writes slice JPEGs, `false` never; by default they are written only when some were cut by `maxSlices` |
|
|
185
|
+
| `sliceWidth` | 768 | full page: max slice width in px (raise it for small text on desktop) |
|
|
186
|
+
| `maxHeight` | 60000 | full page: CSS px cap |
|
|
187
|
+
| `reducedMotion` | false | emulate `prefers-reduced-motion: reduce` |
|
|
188
|
+
| `waitFor`, `waitMs`, `colorScheme`, `outDir`, `timeoutMs` | | as in the CLI |
|
|
189
|
+
| `inline` | true | return images, not just paths |
|
|
190
|
+
|
|
191
|
+
The result starts with a plain-text block: one line per device (or the error
|
|
192
|
+
and hint), followed by the JSON summary (file paths, pixel sizes,
|
|
193
|
+
`scrollHeight`, `capturedHeight`, `segments`, `clipped`, `slices`, HTTP status,
|
|
194
|
+
final URL, title, console errors, `error`/`code`/`hint`).
|
|
195
|
+
|
|
196
|
+
Then the images:
|
|
197
|
+
|
|
198
|
+
- Without `fullPage`: one JPEG preview per device (the framed shot when
|
|
199
|
+
`bezels`), at most 1024 px on the long side.
|
|
200
|
+
- With `fullPage`: the framed first screen when `bezels`, labelled
|
|
201
|
+
`iphone-15 · first screen in bezel`, then the whole page as top-to-bottom
|
|
202
|
+
slices, each one viewport tall and labelled
|
|
203
|
+
`iphone-15 · slice 2/7 · y=852–1704 css px`. A three-device review of a
|
|
204
|
+
typical marketing page is roughly 0.5 MB of JPEG.
|
|
205
|
+
|
|
206
|
+
<picture>
|
|
207
|
+
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/akintola4/rpc-agent/main/docs/media/mcp-slices-dark.png">
|
|
208
|
+
<img alt="The first five labelled full-page slices returned for an iPhone 15 capture" src="https://raw.githubusercontent.com/akintola4/rpc-agent/main/docs/media/mcp-slices-light.png">
|
|
209
|
+
</picture>
|
|
210
|
+
|
|
211
|
+
When a page has more slices than `maxSlices`, the text says which ones were
|
|
212
|
+
skipped (`slices 11-26 (y=8520-21656 css px) skipped inline`), all slices are
|
|
213
|
+
written to disk and the summary gives their paths and the full PNG, so the
|
|
214
|
+
agent can Read the rest without slicing anything itself.
|
|
215
|
+
|
|
216
|
+
### `list_devices`
|
|
217
|
+
|
|
218
|
+
Takes an optional `category` (`apple-phone`, `android-phone`, `tablet`,
|
|
219
|
+
`laptop`) and returns ids, sizes and aliases.
|
|
220
|
+
|
|
221
|
+
Files go to `outDir`, which is resolved against the server's working
|
|
222
|
+
directory. Claude Code and Cursor start the server in the project root.
|
|
223
|
+
|
|
224
|
+
### Claude Code
|
|
225
|
+
|
|
226
|
+
```sh
|
|
227
|
+
claude mcp add --scope user rpc -- npx -y rpc-agent mcp
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
Drop `--scope user` to add it to the current project only. Run
|
|
231
|
+
`npx rpc-agent install` once first so the server has a browser. If
|
|
232
|
+
`rpc-agent` is installed globally, `claude mcp add --scope user rpc -- rpc
|
|
233
|
+
mcp` skips the npx lookup on each start.
|
|
234
|
+
|
|
235
|
+
From a clone, point it at the build instead (the path must be absolute,
|
|
236
|
+
and Claude Code needs a restart or `/mcp` reconnect after rebuilding):
|
|
237
|
+
|
|
238
|
+
```sh
|
|
239
|
+
claude mcp add --scope user rpc -- node "$(pwd)/dist/cli.js" mcp
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
If you use the Claude Code sandbox, pages on hosts outside its network
|
|
243
|
+
allowlist fail with `ERR_NAME_NOT_RESOLVED` or a proxy error; the hint says
|
|
244
|
+
so. Add the domain to the allowlist.
|
|
245
|
+
|
|
246
|
+
### Cursor
|
|
247
|
+
|
|
248
|
+
`~/.cursor/mcp.json` (global) or `.cursor/mcp.json` (per project):
|
|
249
|
+
|
|
250
|
+
```json
|
|
251
|
+
{
|
|
252
|
+
"mcpServers": {
|
|
253
|
+
"rpc": {
|
|
254
|
+
"command": "npx",
|
|
255
|
+
"args": ["-y", "rpc-agent", "mcp"]
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
From a clone, use `"command": "node"` and
|
|
262
|
+
`"args": ["/absolute/path/to/rpc-agent/dist/cli.js", "mcp"]`.
|
|
263
|
+
|
|
264
|
+
## Development
|
|
265
|
+
|
|
266
|
+
```sh
|
|
267
|
+
pnpm test # vitest: unit tests plus e2e captures of local fixtures
|
|
268
|
+
pnpm typecheck
|
|
269
|
+
pnpm build
|
|
270
|
+
pnpm smoke:mcp [url] [--full-page] [--devices a,b] [--max-slices n]
|
|
271
|
+
pnpm media # regenerate the README images and GIF (needs ffmpeg)
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
The e2e tests serve `test/fixtures` locally. `tall.html` is 21,656 CSS px
|
|
275
|
+
(64,968 px at DPR 3): the test checks every row of the stitched PNG against
|
|
276
|
+
the known layout across all seams, that the sticky header and a fixed badge
|
|
277
|
+
appear once, that the IntersectionObserver section rendered, and the slice
|
|
278
|
+
count and labels, including through the MCP server. The missing-browser tests
|
|
279
|
+
point `PLAYWRIGHT_BROWSERS_PATH` at an empty temp dir.
|
|
280
|
+
|
|
281
|
+
The README media are built from real captures by `scripts/media/build.ts`;
|
|
282
|
+
`docs/media.md` explains how. The CLI's design notes, and what it borrows
|
|
283
|
+
from the `skills` CLI, are in `docs/cli-design.md`.
|
|
284
|
+
|
|
285
|
+
## Limitations
|
|
286
|
+
|
|
287
|
+
- Chromium only, portrait only. There is no landscape mode, and none of RPC's
|
|
288
|
+
fake browser chrome bars.
|
|
289
|
+
- Scroll-driven animations are captured in their scroll-top state. Entrance
|
|
290
|
+
animations that run once are usually fine after the warm-up scroll; ones
|
|
291
|
+
that reverse when scrolled back (GSAP `toggleActions` with reverse, scrubbed
|
|
292
|
+
timelines) may show their initial state. `reducedMotion` helps on sites that
|
|
293
|
+
respect it.
|
|
294
|
+
- Very tall stitched PNGs are big files; review them through the slices.
|
|
295
|
+
- The bezel geometry is RPC's, unchanged. On kind-default phones the page
|
|
296
|
+
covers the dynamic island or notch, and generic monitors are drawn edge to
|
|
297
|
+
edge with only the stand showing.
|
|
298
|
+
- No auth, cookies, custom headers or scripted interaction before capture.
|
|
299
|
+
- Every MCP call launches a fresh Chromium, which adds about a second.
|
|
300
|
+
|
|
301
|
+
## License
|
|
302
|
+
|
|
303
|
+
MIT. Bezel artwork and device data come from Responsive Point Check; see `NOTICE`.
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
<svg width="1442" height="1230" viewBox="0 0 1442 1230" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
+
<rect x="553" y="1223" width="44" height="7" rx="1" fill="url(#paint0_linear_3_131)"/>
|
|
3
|
+
<rect x="843" y="1223" width="44" height="7" rx="1" fill="url(#paint1_linear_3_131)"/>
|
|
4
|
+
<rect width="346" height="223" transform="matrix(-1 0 0 1 893 993)" fill="url(#paint2_linear_3_131)"/>
|
|
5
|
+
<rect width="1440" height="997" rx="24" transform="matrix(-1 0 0 1 1442 1)" fill="#505254"/>
|
|
6
|
+
<rect width="1440" height="999" rx="24" transform="matrix(-1 0 0 1 1440 0)" fill="url(#paint3_linear_3_131)"/>
|
|
7
|
+
<path d="M1440 851H0V975C0 988.255 10.7451 999 24 999H1416C1429.25 999 1440 988.255 1440 975V851Z" fill="url(#paint4_linear_3_131)"/>
|
|
8
|
+
<circle cx="8" cy="8" r="8" transform="matrix(-1 0 0 1 752 9)" fill="#343747"/>
|
|
9
|
+
<g filter="url(#filter0_i_3_131)">
|
|
10
|
+
<circle cx="4" cy="4" r="4" transform="matrix(-1 0 0 1 748 13)" fill="url(#paint5_radial_3_131)"/>
|
|
11
|
+
</g>
|
|
12
|
+
<rect width="346" height="15" transform="matrix(-1 0 0 1 893 1212)" fill="url(#paint6_linear_3_131)"/>
|
|
13
|
+
<defs>
|
|
14
|
+
<filter id="filter0_i_3_131" x="740" y="12" width="8" height="9" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
|
15
|
+
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
|
16
|
+
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
|
17
|
+
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
|
|
18
|
+
<feOffset dy="-1"/>
|
|
19
|
+
<feGaussianBlur stdDeviation="3"/>
|
|
20
|
+
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
|
|
21
|
+
<feColorMatrix type="matrix" values="0 0 0 0 0.0392157 0 0 0 0 0.0431373 0 0 0 0 0.0509804 0 0 0 1 0"/>
|
|
22
|
+
<feBlend mode="normal" in2="shape" result="effect1_innerShadow_3_131"/>
|
|
23
|
+
</filter>
|
|
24
|
+
<linearGradient id="paint0_linear_3_131" x1="575" y1="1223" x2="575" y2="1230" gradientUnits="userSpaceOnUse">
|
|
25
|
+
<stop stop-color="#19191A"/>
|
|
26
|
+
<stop offset="1" stop-color="#636569"/>
|
|
27
|
+
</linearGradient>
|
|
28
|
+
<linearGradient id="paint1_linear_3_131" x1="865" y1="1223" x2="865" y2="1230" gradientUnits="userSpaceOnUse">
|
|
29
|
+
<stop stop-color="#19191A"/>
|
|
30
|
+
<stop offset="1" stop-color="#636569"/>
|
|
31
|
+
</linearGradient>
|
|
32
|
+
<linearGradient id="paint2_linear_3_131" x1="173" y1="0" x2="173" y2="223" gradientUnits="userSpaceOnUse">
|
|
33
|
+
<stop stop-color="#303236"/>
|
|
34
|
+
<stop offset="0.873392" stop-color="#8C8F93"/>
|
|
35
|
+
<stop offset="0.924622" stop-color="#BABABA"/>
|
|
36
|
+
<stop offset="0.957999" stop-color="#999B9E"/>
|
|
37
|
+
<stop offset="0.992152" stop-color="#4D4D4D"/>
|
|
38
|
+
</linearGradient>
|
|
39
|
+
<linearGradient id="paint3_linear_3_131" x1="1399.5" y1="-0.000109302" x2="483" y2="862.5" gradientUnits="userSpaceOnUse">
|
|
40
|
+
<stop stop-color="#28282A"/>
|
|
41
|
+
<stop offset="1" stop-color="#18191B"/>
|
|
42
|
+
</linearGradient>
|
|
43
|
+
<linearGradient id="paint4_linear_3_131" x1="720" y1="851" x2="720" y2="999" gradientUnits="userSpaceOnUse">
|
|
44
|
+
<stop stop-color="#535457"/>
|
|
45
|
+
<stop offset="1" stop-color="#43464C"/>
|
|
46
|
+
</linearGradient>
|
|
47
|
+
<radialGradient id="paint5_radial_3_131" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(4 4) rotate(90) scale(4)">
|
|
48
|
+
<stop stop-color="#55A0FF"/>
|
|
49
|
+
<stop offset="0.513343" stop-color="#214D89"/>
|
|
50
|
+
<stop offset="1" stop-color="#10182A"/>
|
|
51
|
+
</radialGradient>
|
|
52
|
+
<linearGradient id="paint6_linear_3_131" x1="346" y1="15.0001" x2="-1.64163e-05" y2="16.0001" gradientUnits="userSpaceOnUse">
|
|
53
|
+
<stop stop-color="#727476"/>
|
|
54
|
+
<stop offset="0.0196622" stop-color="#B6B6B9"/>
|
|
55
|
+
<stop offset="0.0393102" stop-color="#66696D"/>
|
|
56
|
+
<stop offset="0.0913451" stop-color="#898A8F"/>
|
|
57
|
+
<stop offset="0.948172" stop-color="#898A8F"/>
|
|
58
|
+
<stop offset="0.977921" stop-color="#66696D"/>
|
|
59
|
+
<stop offset="0.991869" stop-color="#B6B6B9"/>
|
|
60
|
+
<stop offset="1" stop-color="#727476"/>
|
|
61
|
+
</linearGradient>
|
|
62
|
+
</defs>
|
|
63
|
+
</svg>
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
<svg width="633" height="908" viewBox="0 0 633 908" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
+
<g filter="url(#filter0_dd_40_479)">
|
|
3
|
+
<path d="M4 37C4 17.67 19.67 2 39 2H594C613.33 2 629 17.67 629 37V867C629 886.33 613.33 902 594 902H39C19.67 902 4 886.33 4 867V37Z" fill="#3A4245"/>
|
|
4
|
+
</g>
|
|
5
|
+
<path d="M8 38C8 20.3269 22.3269 6 40 6H593C610.673 6 625 20.3269 625 38V866C625 883.673 610.673 898 593 898H40C22.3269 898 8 883.673 8 866V38Z" fill="#121515"/>
|
|
6
|
+
<path fill-rule="evenodd" clip-rule="evenodd" d="M296 867.5C296 878.822 305.178 888 316.5 888C327.822 888 337 878.822 337 867.5C337 856.178 327.822 847 316.5 847C305.178 847 296 856.178 296 867.5ZM334.397 867.5C334.397 877.384 326.384 885.397 316.5 885.397C306.616 885.397 298.603 877.384 298.603 867.5C298.603 857.616 306.616 849.603 316.5 849.603C326.384 849.603 334.397 857.616 334.397 867.5Z" fill="#262C2D"/>
|
|
7
|
+
<path d="M27 68C27 66.8954 27.8954 66 29 66H604C605.105 66 606 66.8954 606 68V835C606 836.105 605.105 837 604 837H29C27.8954 837 27 836.105 27 835V68Z" fill="#262C2D"/>
|
|
8
|
+
<path fill-rule="evenodd" clip-rule="evenodd" d="M316.5 40C318.985 40 321 37.9853 321 35.5C321 33.0147 318.985 31 316.5 31C314.015 31 312 33.0147 312 35.5C312 37.9853 314.015 40 316.5 40Z" fill="#262C2D"/>
|
|
9
|
+
<path fill-rule="evenodd" clip-rule="evenodd" d="M316.5 38.3125C318.053 38.3125 319.312 37.0533 319.312 35.5C319.312 33.9467 318.053 32.6875 316.5 32.6875C314.947 32.6875 313.688 33.9467 313.688 35.5C313.688 37.0533 314.947 38.3125 316.5 38.3125Z" fill="#121515"/>
|
|
10
|
+
<path opacity="0.4" fill-rule="evenodd" clip-rule="evenodd" d="M316.5 34.9375C316.811 34.9375 317.062 34.6857 317.062 34.375C317.062 34.0643 316.811 33.8125 316.5 33.8125C316.189 33.8125 315.938 34.0643 315.938 34.375C315.938 34.6857 316.189 34.9375 316.5 34.9375Z" fill="#636F73"/>
|
|
11
|
+
<defs>
|
|
12
|
+
<filter id="filter0_dd_40_479" x="0" y="0" width="633" height="908" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
|
13
|
+
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
|
14
|
+
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
|
|
15
|
+
<feOffset/>
|
|
16
|
+
<feGaussianBlur stdDeviation="1"/>
|
|
17
|
+
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0.0823529 0 0 0 0 0.25098 0 0 0 0.14 0"/>
|
|
18
|
+
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_40_479"/>
|
|
19
|
+
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
|
|
20
|
+
<feOffset dy="2"/>
|
|
21
|
+
<feGaussianBlur stdDeviation="2"/>
|
|
22
|
+
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0.0823529 0 0 0 0 0.25098 0 0 0 0.05 0"/>
|
|
23
|
+
<feBlend mode="normal" in2="effect1_dropShadow_40_479" result="effect2_dropShadow_40_479"/>
|
|
24
|
+
<feBlend mode="normal" in="SourceGraphic" in2="effect2_dropShadow_40_479" result="shape"/>
|
|
25
|
+
</filter>
|
|
26
|
+
</defs>
|
|
27
|
+
</svg>
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
<svg width="427" height="858" viewBox="0 0 427 858" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
+
<g clip-path="url(#clip0_4_4689)">
|
|
3
|
+
<path fill-rule="evenodd" clip-rule="evenodd" d="M424 197H425C426.105 197 427 197.895 427 199V295C427 296.105 426.105 297 425 297H424V197Z" fill="#121515"/>
|
|
4
|
+
<path fill-rule="evenodd" clip-rule="evenodd" d="M0 257C0 255.895 0.895431 255 2 255H3V318H2C0.895431 318 0 317.105 0 316V257Z" fill="#121515"/>
|
|
5
|
+
<path fill-rule="evenodd" clip-rule="evenodd" d="M0 178C0 176.895 0.895431 176 2 176H3V239H2C0.895431 239 0 238.105 0 237V178Z" fill="#121515"/>
|
|
6
|
+
<path fill-rule="evenodd" clip-rule="evenodd" d="M0 117C0 115.895 0.895431 115 2 115H3V148H2C0.895431 148 0 147.105 0 146V117Z" fill="#121515"/>
|
|
7
|
+
<g filter="url(#filter0_dd_4_4689)">
|
|
8
|
+
<path fill-rule="evenodd" clip-rule="evenodd" d="M3 63C3 28.2061 31.2061 0 66 0H361C395.794 0 424 28.2061 424 63V795C424 829.794 395.794 858 361 858H66C31.2061 858 3 829.794 3 795V63Z" fill="#3A4245"/>
|
|
9
|
+
</g>
|
|
10
|
+
<path fill-rule="evenodd" clip-rule="evenodd" d="M8 63C8 30.9675 33.9675 5 66 5H361C393.033 5 419 30.9675 419 63V795C419 827.033 393.033 853 361 853H66C33.9675 853 8 827.033 8 795V63Z" fill="#121515"/>
|
|
11
|
+
<path fill-rule="evenodd" clip-rule="evenodd" d="M259 40C263.418 40 267 36.4183 267 32C267 27.5817 263.418 24 259 24C254.582 24 251 27.5817 251 32C251 36.4183 254.582 40 259 40Z" fill="#262C2D"/>
|
|
12
|
+
<path fill-rule="evenodd" clip-rule="evenodd" d="M259 37C261.761 37 264 34.7614 264 32C264 29.2386 261.761 27 259 27C256.239 27 254 29.2386 254 32C254 34.7614 256.239 37 259 37Z" fill="#121515"/>
|
|
13
|
+
<path opacity="0.4" fill-rule="evenodd" clip-rule="evenodd" d="M259 31C259.552 31 260 30.5523 260 30C260 29.4477 259.552 29 259 29C258.448 29 258 29.4477 258 30C258 30.5523 258.448 31 259 31Z" fill="#636F73"/>
|
|
14
|
+
<path fill-rule="evenodd" clip-rule="evenodd" d="M188 32C188 30.3431 189.343 29 191 29H236C237.657 29 239 30.3431 239 32C239 33.6569 237.657 35 236 35H191C189.343 35 188 33.6569 188 32Z" fill="#262C2D"/>
|
|
15
|
+
</g>
|
|
16
|
+
<defs>
|
|
17
|
+
<filter id="filter0_dd_4_4689" x="-1" y="-2" width="429" height="866" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
|
18
|
+
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
|
19
|
+
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
|
|
20
|
+
<feOffset/>
|
|
21
|
+
<feGaussianBlur stdDeviation="1"/>
|
|
22
|
+
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0.0823529 0 0 0 0 0.25098 0 0 0 0.14 0"/>
|
|
23
|
+
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_4_4689"/>
|
|
24
|
+
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
|
|
25
|
+
<feOffset dy="2"/>
|
|
26
|
+
<feGaussianBlur stdDeviation="2"/>
|
|
27
|
+
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0.0823529 0 0 0 0 0.25098 0 0 0 0.05 0"/>
|
|
28
|
+
<feBlend mode="normal" in2="effect1_dropShadow_4_4689" result="effect2_dropShadow_4_4689"/>
|
|
29
|
+
<feBlend mode="normal" in="SourceGraphic" in2="effect2_dropShadow_4_4689" result="shape"/>
|
|
30
|
+
</filter>
|
|
31
|
+
<clipPath id="clip0_4_4689">
|
|
32
|
+
<rect width="427" height="858" fill="white"/>
|
|
33
|
+
</clipPath>
|
|
34
|
+
</defs>
|
|
35
|
+
</svg>
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
<svg width="423" height="858" viewBox="0 0 423 858" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
+
<g clip-path="url(#clip0_382_904)">
|
|
3
|
+
<path d="M420 230H421.5C422.328 230 423 230.672 423 231.5V341.5C423 342.328 422.328 343 421.5 343H420V230Z" fill="#446087"/>
|
|
4
|
+
<path d="M2.99988 366L1.49987 366C0.671445 366 -0.000127257 365.328 -0.000127184 364.5L-0.000121414 298.5C-0.000121342 297.672 0.671452 297 1.49988 297L2.99988 297L2.99988 366Z" fill="#446087"/>
|
|
5
|
+
<path d="M2.99988 275L1.49987 275C0.671445 275 -0.000127257 274.328 -0.000127184 273.5L-0.000121414 207.5C-0.000121342 206.672 0.671452 206 1.49988 206L2.99988 206L2.99988 275Z" fill="#446087"/>
|
|
6
|
+
<path d="M2.99988 170L1.49988 170C0.671449 170 -0.000124396 169.328 -0.000124323 168.5L-0.000121613 137.5C-0.000121541 136.672 0.671451 136 1.49988 136L2.99988 136L2.99988 170Z" fill="#446087"/>
|
|
7
|
+
<path d="M3 91C3 66.8033 3 54.705 6.18133 44.9139C12.611 25.1254 28.1254 9.61099 47.9139 3.18133C57.705 0 69.8033 0 94 0H329C353.197 0 365.295 0 375.086 3.18133C394.875 9.61099 410.389 25.1254 416.819 44.9139C420 54.705 420 66.8033 420 91V767C420 791.197 420 803.295 416.819 813.086C410.389 832.875 394.875 848.389 375.086 854.819C365.295 858 353.197 858 329 858H94C69.8033 858 57.705 858 47.9139 854.819C28.1254 848.389 12.611 832.875 6.18133 813.086C3 803.295 3 791.197 3 767V91Z" fill="#102948"/>
|
|
8
|
+
<path fill-rule="evenodd" clip-rule="evenodd" d="M329.4 3H93.6C69.6199 3 58.1042 3.02467 48.8409 6.0345C29.9658 12.1674 15.1674 26.9658 9.0345 45.8409C6.02467 55.1042 6 66.6199 6 90.6V767.4C6 791.38 6.02467 802.896 9.0345 812.159C15.1674 831.034 29.9658 845.833 48.8409 851.966C58.1042 854.975 69.6199 855 93.6 855H329.4C353.38 855 364.896 854.975 374.159 851.966C393.034 845.833 407.833 831.034 413.966 812.159C416.975 802.896 417 791.38 417 767.4V90.6C417 66.6199 416.975 55.1042 413.966 45.8409C407.833 26.9658 393.034 12.1674 374.159 6.0345C364.896 3.02467 353.38 3 329.4 3ZM7.13238 45.2229C4 54.8634 4 66.7756 4 90.6V767.4C4 791.224 4 803.137 7.13238 812.777C13.4631 832.261 28.7389 847.537 48.2229 853.868C57.8634 857 69.7756 857 93.6 857H329.4C353.224 857 365.137 857 374.777 853.868C394.261 847.537 409.537 832.261 415.868 812.777C419 803.137 419 791.224 419 767.4V90.6C419 66.7756 419 54.8634 415.868 45.2229C409.537 25.7389 394.261 10.4631 374.777 4.13238C365.137 1 353.224 1 329.4 1H93.6C69.7756 1 57.8634 1 48.2229 4.13238C28.7389 10.4631 13.4631 25.7389 7.13238 45.2229Z" fill="#446087"/>
|
|
9
|
+
<path d="M8 89C8 66.6646 8 55.4969 10.9366 46.459C16.8717 28.1927 31.1927 13.8717 49.459 7.93661C58.4969 5 69.6646 5 92 5H331C353.335 5 364.503 5 373.541 7.93661C391.807 13.8717 406.128 28.1927 412.063 46.459C415 55.4969 415 66.6646 415 89V769C415 791.335 415 802.503 412.063 811.541C406.128 829.807 391.807 844.128 373.541 850.063C364.503 853 353.335 853 331 853H92C69.6646 853 58.4969 853 49.459 850.063C31.1927 844.128 16.8717 829.807 10.9366 811.541C8 802.503 8 791.335 8 769V89Z" fill="#121515"/>
|
|
10
|
+
<path d="M329 0H338V5H329V0Z" fill="#48627E"/>
|
|
11
|
+
<path d="M415 86H420V95H415V86Z" fill="#48627E"/>
|
|
12
|
+
<path d="M3 86H8V95H3V86Z" fill="#48627E"/>
|
|
13
|
+
<path d="M3 763H8V772H3V763Z" fill="#48627E"/>
|
|
14
|
+
<path d="M415 763H420V772H415V763Z" fill="#48627E"/>
|
|
15
|
+
<path d="M85 853H94V858H85V853Z" fill="#48627E"/>
|
|
16
|
+
<path fill-rule="evenodd" clip-rule="evenodd" d="M258 44C262.418 44 266 40.4183 266 36C266 31.5817 262.418 28 258 28C253.582 28 250 31.5817 250 36C250 40.4183 253.582 44 258 44Z" fill="#262C2D"/>
|
|
17
|
+
<path fill-rule="evenodd" clip-rule="evenodd" d="M258 41C260.761 41 263 38.7614 263 36C263 33.2386 260.761 31 258 31C255.239 31 253 33.2386 253 36C253 38.7614 255.239 41 258 41Z" fill="#121515"/>
|
|
18
|
+
<path opacity="0.4" fill-rule="evenodd" clip-rule="evenodd" d="M258 35C258.552 35 259 34.5523 259 34C259 33.4477 258.552 33 258 33C257.448 33 257 33.4477 257 34C257 34.5523 257.448 35 258 35Z" fill="#636F73"/>
|
|
19
|
+
<path fill-rule="evenodd" clip-rule="evenodd" d="M185 36C185 34.3431 186.343 33 188 33H235C236.657 33 238 34.3431 238 36C238 37.6569 236.657 39 235 39H188C186.343 39 185 37.6569 185 36Z" fill="#262C2D"/>
|
|
20
|
+
</g>
|
|
21
|
+
<defs>
|
|
22
|
+
<clipPath id="clip0_382_904">
|
|
23
|
+
<rect width="423" height="858" fill="white"/>
|
|
24
|
+
</clipPath>
|
|
25
|
+
</defs>
|
|
26
|
+
</svg>
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
<svg width="423" height="858" viewBox="0 0 423 858" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
+
<g clip-path="url(#clip0_348_1)">
|
|
3
|
+
<path d="M420 240H421.5C422.328 240 423 240.672 423 241.5V331.5C423 332.328 422.328 333 421.5 333H420V240Z" fill="#213744"/>
|
|
4
|
+
<path d="M3 353L1.49999 353C0.671567 353 -5.1865e-06 352.328 -5.11407e-06 351.5L-2.18399e-07 295.5C-1.45976e-07 294.672 0.671573 294 1.5 294L3.00001 294L3 353Z" fill="#213744"/>
|
|
5
|
+
<path d="M3 278L1.49999 278C0.671567 278 -5.1865e-06 277.328 -5.11407e-06 276.5L-2.18399e-07 220.5C-1.45976e-07 219.672 0.671573 219 1.5 219L3.00001 219L3 278Z" fill="#213744"/>
|
|
6
|
+
<path d="M3 193L1.5 193C0.671571 193 -2.32548e-06 192.328 -2.25305e-06 191.5L-6.7482e-08 166.5C4.94129e-09 165.672 0.671573 165 1.5 165L3 165L3 193Z" fill="#213744"/>
|
|
7
|
+
<path d="M3 91C3 66.8033 3 54.705 6.18133 44.9139C12.611 25.1254 28.1254 9.61099 47.9139 3.18133C57.705 0 69.8033 0 94 0H329C353.197 0 365.295 0 375.086 3.18133C394.875 9.61099 410.389 25.1254 416.819 44.9139C420 54.705 420 66.8033 420 91V767C420 791.197 420 803.295 416.819 813.086C410.389 832.875 394.875 848.389 375.086 854.819C365.295 858 353.197 858 329 858H94C69.8033 858 57.705 858 47.9139 854.819C28.1254 848.389 12.611 832.875 6.18133 813.086C3 803.295 3 791.197 3 767V91Z" fill="#213744"/>
|
|
8
|
+
<path fill-rule="evenodd" clip-rule="evenodd" d="M329.4 2H93.6C69.6978 2 57.9838 2.01234 48.5319 5.08344C29.3523 11.3153 14.3153 26.3523 8.08344 45.5319C5.01234 54.9838 5 66.6978 5 90.6V767.4C5 791.302 5.01234 803.016 8.08344 812.468C14.3153 831.648 29.3523 846.685 48.5319 852.917C57.9838 855.988 69.6978 856 93.6 856H329.4C353.302 856 365.016 855.988 374.468 852.917C393.648 846.685 408.685 831.648 414.917 812.468C417.988 803.016 418 791.302 418 767.4V90.6C418 66.6978 417.988 54.9838 414.917 45.5319C408.685 26.3523 393.648 11.3153 374.468 5.08344C365.016 2.01234 353.302 2 329.4 2ZM7.13238 45.2229C4 54.8634 4 66.7756 4 90.6V767.4C4 791.224 4 803.137 7.13238 812.777C13.4631 832.261 28.7389 847.537 48.2229 853.868C57.8634 857 69.7756 857 93.6 857H329.4C353.224 857 365.137 857 374.777 853.868C394.261 847.537 409.537 832.261 415.868 812.777C419 803.137 419 791.224 419 767.4V90.6C419 66.7756 419 54.8634 415.868 45.2229C409.537 25.7389 394.261 10.4631 374.777 4.13238C365.137 1 353.224 1 329.4 1H93.6C69.7756 1 57.8634 1 48.2229 4.13238C28.7389 10.4631 13.4631 25.7389 7.13238 45.2229Z" fill="#8EADC1"/>
|
|
9
|
+
<path d="M8 89C8 66.6646 8 55.4969 10.9366 46.459C16.8717 28.1927 31.1927 13.8717 49.459 7.93661C58.4969 5 69.6646 5 92 5H331C353.335 5 364.503 5 373.541 7.93661C391.807 13.8717 406.128 28.1927 412.063 46.459C415 55.4969 415 66.6646 415 89V769C415 791.335 415 802.503 412.063 811.541C406.128 829.807 391.807 844.128 373.541 850.063C364.503 853 353.335 853 331 853H92C69.6646 853 58.4969 853 49.459 850.063C31.1927 844.128 16.8717 829.807 10.9366 811.541C8 802.503 8 791.335 8 769V89Z" fill="#121515"/>
|
|
10
|
+
<path d="M331 0H337V5H331V0Z" fill="#36454C"/>
|
|
11
|
+
<path d="M415 86H420V92H415V86Z" fill="#36454C"/>
|
|
12
|
+
<path d="M3 86H8V92H3V86Z" fill="#36454C"/>
|
|
13
|
+
<path d="M3 766H8V772H3V766Z" fill="#36454C"/>
|
|
14
|
+
<path d="M415 766H420V772H415V766Z" fill="#36454C"/>
|
|
15
|
+
<path d="M86 853H92V858H86V853Z" fill="#36454C"/>
|
|
16
|
+
<path fill-rule="evenodd" clip-rule="evenodd" d="M250 37C253.866 37 257 33.866 257 30C257 26.134 253.866 23 250 23C246.134 23 243 26.134 243 30C243 33.866 246.134 37 250 37Z" fill="#262C2D"/>
|
|
17
|
+
<path fill-rule="evenodd" clip-rule="evenodd" d="M250 34.375C252.416 34.375 254.375 32.4162 254.375 30C254.375 27.5838 252.416 25.625 250 25.625C247.584 25.625 245.625 27.5838 245.625 30C245.625 32.4162 247.584 34.375 250 34.375Z" fill="#121515"/>
|
|
18
|
+
<path opacity="0.4" fill-rule="evenodd" clip-rule="evenodd" d="M250 29.125C250.483 29.125 250.875 28.7332 250.875 28.25C250.875 27.7668 250.483 27.375 250 27.375C249.517 27.375 249.125 27.7668 249.125 28.25C249.125 28.7332 249.517 29.125 250 29.125Z" fill="#636F73"/>
|
|
19
|
+
<path fill-rule="evenodd" clip-rule="evenodd" d="M190 30C190 28.3431 191.343 27 193 27H230C231.657 27 233 28.3431 233 30C233 31.6569 231.657 33 230 33H193C191.343 33 190 31.6569 190 30Z" fill="#262C2D"/>
|
|
20
|
+
</g>
|
|
21
|
+
<defs>
|
|
22
|
+
<clipPath id="clip0_348_1">
|
|
23
|
+
<rect width="423" height="858" fill="white"/>
|
|
24
|
+
</clipPath>
|
|
25
|
+
</defs>
|
|
26
|
+
</svg>
|