🏠 back to Observable

How to test if a notebook exists


What is the best way to test if a notebook exists?

For example, ABC does not exists, while X-Matrix does exist.

My goal is to have a little helper function notebook(n) that inserts a link in md when using md`${notebook(x-matrix)}`and notebook n exists for @martien.


You can try building off of this function (edited with @mootari’s suggestion below!):

async function notebookExists(nbID) {
  const nbURL = nbID.match(/\//) ? nbID : 'd/'+nbID;
  try {
    // need to fetch from this API url for CORS reasons
    await fetch('https://api.observablehq.com/'+nbURL+'.js', {method: 'HEAD'});
    // do stuff
    return "notebook exists!";
  } catch (e) {
    // do other stuff
    return "notebook doesn't exist!";

Note that this is an async function so you’ll need to call it with “await”, otherwise you’ll see a bunch of promises in unexpected places.


You can perform a HEAD request to the JS file to avoid downloading the whole notebook:

Edit: I’d advise against using await though, as it will prevent the cell from rendering before all checks have been completed. I’ve added an example that adds the links after the cell has already rendered.


Wow, what a quick and helpful and practical response. Thank you very much.

Will look into the various options.

Sunday will probably have some time to implement this.


Wow, excellent. I’ll pick one of the options so swiftly provided by you Observables. Probably Sunday. Thank you very. much!


Let me see if I understand:

  • both link() and linkDelayed() use exists()
  • exists() is async and has await built in
    • then what is the use of await in link() as well as in the md text? seems superfluous and confusing (to me at least)

I like the fact that the md gets rendered, while the link shows up shortly after. Feels a bit magical.

So, I’ll pick linkDelayed(). Is calling that lazyLink() appropriate?

Hat tip to both of you gentlemen.

  • link() has to process the result of exists() in order to return the appropriate value. Removing the await would evaluate the promise returned from exists() as a truthy value (and thus always return a link).
  • md processes everything inside it synchronously. If you removed the await you’d get [Object Promise].

Very! Also, feel free to name it whatever you want. :slight_smile: