Use of download code ?

I wonder what is the use of the “download code” function available in the upper menu.
I supposed it provides with the ability to download the code of the html version of a public shared notebook (or not public if mine). But when I tried to open the index.html on my local machine, it delivers a blank page :worried:. Surprisng because all the files seem to be available : index.html, index.js, inspector.css, package.json, and runtime.js.
So I deduced that I certainly did not understand the purpose of this function.
Could someone explain ?
Thank you

1 Like

If you open your browser’s console you’ll see a message like the following:

Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at file:///path/to/downloading-and-embedding-notebooks/index.js. (Reason: CORS request not http).

Here’s a page on that error, which has to do with the security model in the browser.

Note that the README in the tarball says this:

View this notebook in your browser by running a web server in this folder. For

python -m SimpleHTTPServer

So, you must launch a local web server to view the file.

Indeed I read The README file.
Sorry but I don’t understand what means “running a web server”.
If one achieves this with “python -m SimpleHTTPServer”, I tip this in the console and it failed.
Anyway I installed the “Web Server for Chrome” application. But it revealed as non efficient solution.

An easy way around this is to upload the downloaded code to GitHub and view it through a published version of your repository.

1 Like

Thank you for suggestion.
I’ll try it even if I don’t understand why my local process doesn’t work.

It would be great if index.html displayed something relevant in that very common case. (Issue similar to What's your method to compress FileAttachements? ?)


Whole-heartedly agree with the sentiments being expressed here, Observable is not user-friendly at all.

Using the same ‘download’ method described above, I am trying to grab and run D3 Sankey code from here…

just like I would do here from the blocks dot org site…

These seem to be the parts I need that I can easily get from blocks:

  1. sankey.js
  2. d3.min.js
  3. data.json
  4. index.html

Then I drop these files in a folder in my node app, run my node server, then go to the Sankey folder like this…
/localhost:5000 - Sankey-Parallel-Sets - index dot html
I can view a Sankey I’ve taken from the blocks site.

But the files I downloaded from Observable are confusing and do not carry the same content as seen in the blocks files.

What am I missing, why can’t Observable be as simple as bl.ocks? Yes, I can just use the blocks files (which I am doing), but I wanted to get THE Mike Bostock Sankey files as pointed to from the D3 site, not someone else’s interpretation of them.

Help please! :slight_smile:


Hi @kave, and welcome to the forum!

Just in case you haven’t seen it, please let me begin by referring you to this notebook, which is the ‘official’ guide:

It’s true that Observable has its own way of doing things, and you’re not alone in being frustrated by these differences. I’ll try to unpack some of what’s going on with the downloading method. Because I am a novice user, I will be a bit overly unassuming in this response. I see you know node and a lot of what I am going to write will clearly be basic to you. Please forgive me… my hope here is to try to give a summary response to the general question as I understand it: how can I just download and run an Observable app.

When you click ‘download code’, Observable provides you with a tar archive. To see the contents of this file, you’ll need to ‘open’ it in a manner similar to how you would open a .zip file. In the case of the parallel sets notebook you referenced, the archive content includes these files:

  • dde4715990f04109@246.js
  • index.html
  • index.js
  • inspector.css
  • LICENSE.txt
  • package.json
  • runtime.js

Unlike the bl.ocks example you shared, Observable notebooks are not straight / vanilla javascript. Instead, they’re more akin to a bundled React or even Node.js app in the sense that in order to run, they need a runtime environment. That’s what the runtime.js file provides to you. Most of the rest of the notebook javascript (and other content, which effectively is ‘wrapped’ in javascript cells) is contained in the dde4715990f04109@246.js file – including, in this case, the data (note on this ‘gotcha’ below). Aside from these two files, you’ll also need the index.js and the inspector.css to run a notebook… and you might notice that these are all that’s referenced in the index.html file, which effectively brings all these parts together to run your application. The rest of the files have important functions, but strictly speaking there’re not necessary.

Oh - one big ‘gotcha’ that isn’t well documented (and I’ll see if I can link to threads discussing this in a bit) is that b/c your example has a file attachment, you’ll have to load in the data… but it’s totally obscure: in this case, it involves download the CSV and renaming it to a file called /files/3a1e9bb1ba5d9eb731c86c272fccb2543886aca0ef0b80add89f0471177427c5c6627d5ee5d85d011e44cc14019a0509bf309c6db2d347f9bdf7fe26723432d7 … and you won’t find it in the tar archive.

As Bryan and I were trying to explain above, if your goal is just to grab and run Mike’s example, all you need to do is pull out the five files identified above [runtime.js, dde4715990f04109@246.js,inspector.css,index.jss,index.html], run a server instance, and they will return the visualization. Here are the files served through GitHub to show this:

It’s definitely true that this whole process is very different than just grabbing and pasting in JavaScript from bl.ocks – and there’s an entire thread about the frustrations that people have voiced over this.

To me, I kinda feel like it’s similar to the experience I had first looking at a React.js app: I didn’t see how the parts fit together, it required a lot of effort to get started, and I didn’t really understand why one would bother with the application if one could just write plain JavaScript. What use a runtime? In the case of React, why compile from .jsx, which isn’t Javascript and can’t be stuck into a <script> tag. I never did learn React… but I am doing pretty OK learning Observable. What’s the difference? Firstly, there’s this amazing community here on the forum that answers most of the questions I raise. Secondly, Observable offers me immediate positive reinforcement: I don’t have to reload a server instance, clear a cache, or do any other steps when testing some code. The runtime provides cell interactions that link together components and show me instantly how parts fit, where I break things, and why. I don’t need a separate console screen to explore my data, which helps me a lot. …But this is a digression.

Anyway - maybe this answers your question, maybe not. I guess the long and short is that what you’re missing, so to speak, is that the Observable team made a deliberate choice to move away from rendering D3.js examples as bl.ocks written in plain JavaScript to instead showing them through an application that requires a runtime (the Observable runtime) as a trade-off between the convenience of copy-paste examples and an interactive notebook environment that separates code segment into discreet functional elements. They download feature is intended as a sort of ‘bridge’, as it allows you to take any notebook and serve it without much fuss (as I sought to model here… though given, it was fussy… particularly with respect to file attachments… and the Observable team would do well to document this better.)

With some work, you can also just copy and paste the code from within the parallel sets notebook into script elements in plain JS, and it’d work just fine (since it is essentially a static graph and doesn’t really leverage the power of the runtime)… but for other more complex notebooks, the runtime is the glue, and it helps to allow users to separate out bits of code in blocks while taking care of all the heavy lifting of cell interactions.

I hope this helps!

PS: This is one of my favorite tools for making all of this way easier in terms of embedding a visualization directly in an application:


Thank you so much @aaronkyle for your welcoming and helpful message!

After reading through the I want to learn D3. I don`t want to learn Observable. Is that ok? forum post, I’m still resonating with the folks who don’t understand why D3 ‘requires/is dependent on’ Observable. I think there are a number of good arguments on that post to support extracting/downloading only the necessary files for a D3 viz without needing to host/share/embed/collaborate using Observable.

To your direction about where the titanic.csv file is under attachments, thank you. However, for your example of creating the Vanilla version, it’s unclear what exactly I’m renaming to get the const fileAttachements / data path seen in dde4715990f04109@246.js to work. My take away from your suggestion results in creating this file structure inside my node app…
…|—> files
… … …|—> 3a1e9b… [trunc’d but named as seen above & in the dde4715990f04109@246.js]
… … … … …|—> titanic.csv

If that’s not what I should be doing, please let me know.
Or if it’s easier, what would I need to edit in the dde4715990f04109@246.js file to point directly to the data, titanic.csv?

1 Like

Aaron and Kave,
That file is in the tar archive in a folder called files. Aaron, did you not get that file in your download? You should just edit that file, or you can use your own file and just change line 4 in the file dde4715990f04109@246.js to point to your file:

const fileAttachments = new Map([["titanic.csv",new URL("./files/3a1e9bb1ba5d9eb731c86c272fccb2543886aca0ef0b80add89f0471177427c5c6627d5ee5d85d011e44cc14019a0509bf309c6db2d347f9bdf7fe26723432d7",import.meta.url)]]);

1 Like

Thanks Cobus,

The file/folder you mention does not show in the Download Code .tgz file for the Parallel Sets Sankey…

I have attached an image showing what came in the .tgz.

Very strange! What notebook is this download from? When I download from this notebook, my file has the following:

I updated my thread with the Notebook link

Kave, what are you using to unpack the .tgz file, btw? It looks like you are on Windows, right?

Yes, Windows, Downloading in either Firefox or Chrome and using 7z…

OK, I just tested this, and when I untar it with 7-zip on Windows, that folder is indeed missing. When I seems to be the culprit. When I untar it with WinRAR instead, I see the folder. I suggest trying WinRAR instead of 7-zip.


Thanks for this clarification, @Cobus. I had used a program called PeaZip, which is the only archive program that can un-tar on my Windows 10 work computer (on which I am not able to install anything that my company doesn’t provide). I didn’t think to test this on my Linux machine when writing my reply (sorry!). Glad to know I wasn’t going insane.

@kave - I am happy that you found my reply insightful, and I do appreciate your statement that there are good argument for wishing to decouple d3 examples from their Observable home.

To respond to your question on the conversion of the .csv data file… I think I obscured this when I first tried uploading the .csv file to GitHub straight after downloading (I was just assuming it was missing for some change on downloading file attachments that I I had missed). To be more clear… the /files/3a1e9b… is the .csv file attachment that was uploaded to Mike’s notebook. I meant to link a related discussion, but didn’t immediately find it. I hope @Cobus will correct me if I am wrong, but I think that on upload, Observable converts the name to the file’s hash (presumably to decrease file duplication on their servers), so instead of getting the file as named in the notebook, you get the file by a unique ID that strips out the file extension.


Thank you Cobus and Aaron,

Ok WinRAR did the trick, however I’m back to square one when trying to run these files from my node app.
To Aaron’s recommendation for visualizing on my local without using Observable…

…I’ve done that (and included the now extractable ‘files’ structure) but get this error…

What am I still missing?

Hi @kave -

It looks like you’re still having trouble with your .csv attachment. That’s exactly how my GitHub example looked before I tinkered around. Here’s my GitHub file directory for reference:

To fix this, there are couple of ways (at least). The approach I took was this:

  1. download the titanic.csv file from Mike’s notebook
  2. create a subdirectory called files one level below all the other downloaded files
  3. drop in the titanic.csv file
  4. rename titanic.csv to its hash: 3a1e9bb1ba5d9eb731c86c272fccb2543886aca0ef0b80add89f0471177427c5c6627d5ee5d85d011e44cc14019a0509bf309c6db2d347f9bdf7fe26723432d7

The other approach is the one that @Cobus provided above, referring to the dde4715990f04109@246.js file:

I haven’t tried editing this line as I generally find it easier not to mess with the downloaded code (you may have noticed that I make a ton of typos, and sometimes this results in my breaking things and then going crazy not being able to understand why… :stuck_out_tongue: )

1 Like

Ah, ok it did work as you expressed above, but for some reason it will not work in my latest version of Firefox, it will work in Chrome.
And I’ll try to keep an open mind about working with Observable.
Thank you @aaronkyle & @Cobus for your time today!