Documentation for api.observablehq.com

Hello.

I’m looking for documentation for api.observablehq.com.

I haven’t been able to find anything very coherent about it – just some bits and pieces, here and there.

Is there somewhere that I’ve missed?

My immediate use-case is the programmatic creation and updating of a few notebooks – I’d like to build notebooks which import es6 modules and export each variable independently to allow import { a, b, c } from … in client notebooks, rather than needing to use api.a, api.b, api.c everywhere. :slight_smile:

Hi @pentacular. Other than the API for downloading and embedding notebooks, we don’t yet have a public API. This may be something we offer in the future, and if we do, we will absolutely provide documentation for it. But in the meantime we do not recommend using our internal private API.

I hope one can be developed soon.

It would make integration much easier. :slight_smile:

It’s on our list! We want to be thoughtful about its design and documentation. If you have use cases you’d like to see enabled with a public API, we’d love your input.

1 Like

Where would be the right place for that discussion?

You’re welcome to discuss that here! If you’d prefer a private discussion, you can email support.

Sounds good.

I think there are four major gaps that I see at the moment.
(Although some of these may be gaps in my knowledge)

  1. An inability to create notebooks programmatically.
  2. An inability to create suggestions for notebooks programmatically.
  3. An inability to generate things like markdown programmatically.
  4. An inability to do static es6 module imports.

I’ve been trying out observable with an eye toward using it for documentation and examples.

So to do this, I tried to import the es6 modules of the system to be able to run in observable.

The first roadblock I hit was that you cannot do a static import of an es6 module, and the dynamic import will provide a single variable containing the module.

In order to destructure this module to allow notebooks to use static imports I needed to create a notebook containing the dynamic import, and then one cell per entry to make them individually available for static import via notebook.

This isn’t so terrible for one module, I guess, because it’s a reasonable place to add per module entry documentation, but being able to automate it would make it easier to keep things in sync.

But needing to do this for a significant number of modules becomes a problem – either you need to indirect via Foo.bar, or you need to keep a destructuring notebook up to date.

And this becomes more of an issue when you’re publishing additional modules in various repositories which effectively extend the base api – for example, a gear generation library.

Another thing I’m interested in with respect to observable is producing step-by-step instructions.
It would be great if I could use a little meta-data and then create a notebook which talks about how to do something, shows diagrams, and makes files available for download.

(Do downloadable cell values exist in general? I’ve seen some which offer download, but haven’t seen documentation for how it works yet)

This would require an API to create notebooks, and one to create suggestions to keep the content in sync.

(Or, I guess a function to dynamically create cells?)

Speaking of which, I tried to create a function to reproduce the builtin md# foo behavior, using { return md(’# foo’); }, but it did not work – is there a way to call the builtins or produce cell output that should be treated as markdown?

(I figured out that returning a canvas was sufficient to display it, but don’t see how to generalize this for other cases).

I expect that programmatic interfaces aren’t high on the priority list, but it would be nice to understand how much of the above makes sense, and how well it fits with the vision for observable.

Thanks.

1 Like

Thanks for the great feedback!

A related feature we’ve started work on (though I don’t have a timeline as to when it will land) is to allow destructuring of cells:

This wouldn’t address all of your issues, but it would allow dynamic ES imports to work more like static ES imports, e.g.

({area, line}) = import("d3-shape")

There’s a little bit of information about how downloadable cells work here:

The md function is a tagged template literal, so you’d call it like this (without parens):

{ return md`# foo`; }

If you want to create a function that creates an H1 element, it would be something like this:

function h1(name) {
  return md`# ${name}`;
}

which you would call like so:

h1("foo")

Keep in mind that this doesn’t escape the given name, though, so you can inject HTML or Markdown with this approach. If you want to escape, you can either use hypertext literal or do it manually:

function h1(name) {
  return html`<h1>${document.createTextNode(name)}`;
}
1 Like

Thanks for the tip for using builtins.

It would be nice if there were some kind of generalized file value that carried a mime type and a base64 encoded payload.

This would allow things like pdf or stl generation within a notebook for download.

There’s DOM.download in the standard library to make it easier to download generated content. And here’s a notebook that demonstrates generating a PDF:

1 Like

Ah, I see.

I was thinking of the cell result, but a cell that produces a UI that does download makes sense.

Thanks.

Two more use cases:

  • @nikita-sharov/progress-bar, trying to provide some history / meta on the topic (original source, forks / republications, compilations, public success), following the “read the originals, in the original language” maxime
  • @nikita-sharov/publications, trying to assert the “writing is rewriting” thesis (i.a.)