Puppetromium is a simple web-browser based on Puppeteer. If Chromium and Puppeteer had a love child, it would be this horrible. Probably.
Also, there is no (as in zero "0") client-side scripting (in this browser UI) of any kind. No JavaScript. No ActionScript. No Flash. This crazy-simple remote browser UI is built entirely with HTML and CSS.
With the power ⚡ 💪, my friend, of the following ancient®️ techs©️ from ye olde webbe:
- MJPEG to stream the remote viewport with server-push only
<input type=image src=/viewport.mjpeg>
to capture X and Y co-ordinates of pointer events and post them to the server on click.- targeted forms and named iframes to allow transmitting actions like 'type text' or 'scroll down' without reloading the top-level page.
Mostly as an exercise. To see how simple I get a remote browser that is still minimally usable. But also as an example of why puppeteer is not a great fit for this. And a reminder why I created a whole other browser driving protocol atop the DevTools protocol for my custom remote isolated browser.
Also because I thought people will think a browser UI built with Puppeteer is cool, and it might encourage them to get into remote browsing, and custom browser UIs for cloud browsers, and hack on top of it. I wanted to release something with a very permissive license, that might spark people's imaginations about how they could use this kind of tech in their own project. I wanted something I could build in 1 day (and indeed, it took me around 6 hours). I wanted something where I wasn't restricted by the need to keep the license strict (e.g., AGPL-3.0), in order to preserve my business of selling corporate license exceptions and SaaS deployments.
I wanted to give people a way they could get their toes wet, without having to pay anything, and so they might build their own on top of it. Because the type of people who would probably find this useful to hack on, are not the type of people who want to pay for a corporate license.
A single NodeJS file that serves everything, 350 source lines of code, 6 endpoints (5 GET, 1 POST), 1 export and 3 external imports (express, mjpeg-server, and of course puppeteer).
okay, but how you size the remote browser viewport to roughly match my screen without any client-side JavaScript, what crazy majyck is this?
With, my friend, the following ingenious idea:
/* code to set the viewport approx size without client side JS */
// for all w and h combinations that are relevant
`@media screen and (min-width: ${w}px) and (min-height: ${h}px) {
body {
background-image: url("/set-viewport-dimensions/width/${w}/height/${h}/set.png")
}
}`
app.get('/set-viewport-dimensions/width/:width/height/:height/set.png', async (req, res) => {
const ua = req.headers['user-agent'];
const isMobile = testMobile(ua);
let {width,height} = req.params;
width = parseFloat(width);
height = parseFloat(height);
await page.emulate({
viewport: {
width,
height,
isMobile
},
userAgent: ua
});
...
Alternative install mantras:
$ npx puppetromium@latest 8080
# or
$ npm i -g puppetromium@latest
$ puppetromium 8080
Or:
$ npm i --save puppetromium
Then:
import {start} from 'puppetromium';
start({port:8080, url:'https://jspaint.app'});
Or:
$ git clone https://github.com/i5ik/puppetromium.git
$ cd puppetromium/
$ npm i
$ npm start 8080
It's probably because of puppeteer dependencies. Make sure you have them all installed. I included a bunch of dependency scripts tailed to Debian (which may work on other Linuxes, but your mileage may encounter variability).