This method is a simple way to migrate an Observable notebook to a standalone webpage.
Open the joyplot/index.html file in a browser. It will display the same joyplot as in the PSR B1919+21 Observable notebook.
Alternatively, serve the file from a web server, locally at http://localhost:8000 with:
python3 -m http.server --directory joyplot
or deploy on now.sh (see https://joyplot-96iun3ktp.now.sh/) with:
npx now joyplot
- simple (does not require knowledge about npm, node.js, ES modules, transpilation, or now.sh)
- only one file to manage (index.html)
- allows to render only some cells of the notebook
- requires browser compatibility with ES modules
- no resources are loaded locally (index.html apart), and a lot of HTTP requests
are generated:
- the Observable notebook module
- the runtime.js Observable library (JS)
- package.json, in order to locate the actual d3 library file to import
- the actual d3 library file
- generates an HTTP request to get the data from an external location
- the pulsar.csv data
- does not work locally (offline) since it depends on requests to cdn.jsdeliver.net, api.observablehq.com and to the data file
The steps to adapt the solution to another notebook, say Breakout! are:
-
determine which cells to include in the webpage. For example:
viewof c
(the game),viewof newgame
(the restart button) andviewof speed
(the speed controller) -
adapt the HTML template, replacing
<title>PSR B1919+21</title> (...) <!-- Title of the page --> <h1>PSR B1919+21</h1> <!-- Empty placeholders --> <div id="joyplot"></div>
with
<title>Breakout!</title> (...) <!-- Title of the page --> <h1>Breakout!</h1> <!-- Empty placeholders --> <div id="game"></div> <div id="controls"> <p class="button"></p> <p>Speed: <span class="slider"></span></p> </div>
-
adapt the JavaScript code, replacing:
import notebook from 'https://api.observablehq.com/@fil/tissots-indicatrix.js?v=3'; (...) switch (name) { case 'chart': // render 'chart' notebook cell into <div id="joyplot"></div> return new Inspector(document.querySelector('#joyplot')); break; }
with
import notebook from 'https://api.observablehq.com/@jashkenas/breakout.js?v=3'; (...) switch (name) { case 'viewof c': // render 'viewof c' notebook cell into <div id="game"></div> return new Inspector(document.querySelector('#game')); break; case 'viewof newgame': // render 'viewof newgame' notebook cell into <p class="button"></p> return new Inspector(document.querySelector('#controls .button')); break; case 'viewof speed': // render 'viewof speed' notebook cell into <span class="slider"></span> return new Inspector(document.querySelector('#controls .slider')); break; }
-
see the result in breakout/index.html
See also tissot/index.html for a third example.