🏠 back to Observable

JavaScript, Markdown, HTML, and TeX Cell Modes. OH MY!

JavaScript, Markdown, HTML, and TeX Cell Modes. OH MY!

We’re excited to announce Cell Modes! :writing_hand:

You can choose the mode you want to edit - Javascript, Markdown, HTML and TeX. We want to make it as easy as possible for you to write different types of content, not just code. :revolving_hearts: Better syntax highlighting. No more fussy escaping. It’s not just Javascript!

When you create a new cell, you’ll notice that a menu appears on the right of the editor. You can select the cell mode when editing a new cell.

You can select JavaScript, Markdown, HTML, or TeX as the cell mode.

Once you’ve selected a mode, you can start typing! As you saw above, when editing a cell in Markdown mode, you can simply write plain Markdown and get the output that you want. No more managing the opening and closing backticks of the Markdown tagged template literal, no more need to escape backticks!

See the latest Cell Modes document for more details.

Update via Release Notes


I am Jack’s relief of never having to write \`\`\` again


Nice! Though I use “~~~js” instead of escaped backticks.

Great news! We were discussing only the other day that this would be a more convenient way of creating new cells. Good to see keyboard shortcuts for selecting the cell mode (cycling with arrow keys), and for bold and italic formatting in markdown mode. Is there a similar keyboard shortcut for backtick code formatting inside markdown cells? If not, this would be a great addition allowing most common cell authoring content to be quickly created.

This also opens up the possibility for the same shortcuts generating their html equivalents in html mode, perhaps along with pairing up tags (e.g. when one creates a <p> and equivalent </p> is created after the caret position).

1 Like


Confrontation anxiety / low work self-esteem friendly summary :blush::

The gains don’t out-weight the losses.

  • Template literals are very modular and compose nicely. Typed cells don’t.
  • Template literals empower the community and promote experimentation and collaboration.
  • Having to write ~~~ instead of ``` is a non issue.
  • Additional keyboard shortcuts and mouse operations introduce friction.
  • They don’t play nicely with copy and paste.
  • More UI means less interoperability.
  • This adds more maintenance burden on an obviously overworked team.

Thanks for trying tho :smiling_face_with_three_hearts:!

Frustration fuelled rant :wink: :

A GIF of Michael Scott from "the Office" TV series, screaming "Noooooooo!"

Oh god, no please!

Not having the hassle of typed cells is one of the major features of Observable!

I’ve used other notebooks with typed cells like nextjournal and starboard, typed cells plain suck.

  • They are super inflexible, loose modularity, and don’t compose: Typed cells are a closed set. You want to write a new markup formatter for say ReStructured Text? Tough luck. Unhappy with the Markdown renderer used by observable? Tough luck.
    JS template literals that emit DOM nodes allow you to do all of this and more. They nest and compose nicely, it’s super easy to create first class alternative markup types, and it’s something that really helps community building and collaboration.

  • They solve a non issue: Let’s be real, how often do you REALLY have to do ``` to escape code that you don’t want to run? The whole point of observable is to have an environment of runnable cells, so most of your code will go into those anyways. Also if you want to show stuff like command line input you can just write your own literal for that and get much nicer visuals. And as @keystroke points out, there’s also ~~~.

  • They introduce a lot of friction to the workflow. Setting the type of a cell once might be ok, but doing it over and over and over again is just annoying flow breaking tedium. Creating and changing cell types is probably one of the most performed operations.

  • It breaks copy paste. On long notebooks it’s often easier to simply copy a cell and paste it somewhere else, instead of having to drag the bloody thing to the moon and back. With typed cells you not only have to paste the cell, but also set the cell type. URGH…

  • They further paint observable into a platform corner, where everything has to be done through a UI with no hopes of properly integrating with proper development tools. Text is love!

  • They completely miss the target audience: “Yeah those plot Marks, Scales, Transforms and Facets are easy peasy, but you know what I really struggle with!? having to type * to make my words bold.” - no one ever

And here’s the real kicker! Stuff like this adds to the dumpster fire that you have to maintain. Before this could have been nicely delegated to the community. Ask around who wants to maintain the template literals for specific markup languages, I’m 100% positive that someone would take over as a maintainer. I’d gladly do it if it prevents you from wasting resources like this, and gives you some space to address the ton of bugs that give me misery.
But now it’s within the proprietary boundary of “the editor”, which means it’s another thing on your plate.
Isn’t the prettier fork, the in house diff view, the custom version control management system, the javascript transpiler, the custom dataflow engine, the full text code search, the social media stuff, distributed eventually consistent text editing, an old testament amount of bugs and everything in between enough?
Do you really have to add the insanity inducing madness that is contenteditable and WYSIWYG a problem so nasty that even facebook with it’s billions of dollars and thousands of engineers (including the creators of React), just couldn’t get it half way bug free?
If you’re into suffering that much may I instead recommend wearing a really scratchy undergarment.

The lack of feel for what’s really great about observable (and what isn’t) makes me loose confidence in observables leadership and loose hope that the team will get its priorities straight at least some day.
Who judges and approves those long term maintenance costs while ignoring all the fundamental existing quality issues? Doth thy hubris have no bounds?

Observable notebooks are the closes thing I’ve seen to a bicycle for the mind,
yet observable the company insist on it being a rickshaw. The barrier of entry is already low enough, use the community as a force multiplier by giving it better tools, not flashy features that only look nice as a mockup.

So please. Kill it with fire.

Something that would have made the entire system more powerful and more flexible would have been the ability for self modifying cells. By adding a replaceContent(newValue) to the standard library we’d not only have gotten the ability to write our own WYSIWYG editors for markdown and HTML, but also for all kinds of custom data types, like tables, lists, and the ability to have code and interactions that persistently reflect in the notebooks without the need to connect to some external service or database, something which I’ve needed countless times.


Having used Jupyter for many years, I agree that the ease of using a template literal, rather than switching modes, is a very nice aspect of Observable. Fortunately, you can still use template literals in Javascript mode. :slight_smile:


Disclaimer: I’m clearly not the target audience for cell modes; it doesn’t really harm me to have them available for other people, and since nobody is forced to use them, they aren’t really in my way. Evaluation of their effectiveness should probably be based on user-testing someone else.

I’m also not super sold on modes (and for now don’t really intend to use them in my own notebooks), and have been generally very happy with having everything be ‘just (reactive-ized) javascript’ and using template literals – though I do wish we could add custom syntax highlighting of the content of template literals.

Most of my notebooks are filled with LaTeX formulas (for example, @jrus/planisphere), but I never make a bare TeX cell, so I can’t use this cell mode. I’ve considered trying to make a markdown + tex template that parses out some particular bit of syntax and automatically passes the content to KaTeX, but have found the use of $ as a shortcut for tex and $$ as a shortcut for tex.block to be a acceptable enough substitute that I haven’t bothered (typing ${$``} is only moderately more annoying than typing \(\) and ${$$`\begin{aligned} ... \end{aligned}`} vs. \[\begin{aligned} ... \end{aligned}\] are about the same). Almost always my LaTeX shows up inside markdown cells, sometimes wrapped in other helper functions to make it more friendly for mobile displays.

About half of my cells are markdown cells, but between many of them having a cell name (this lets me link directly to them, and makes them show up clearly in the top-right “minimap” – which I find convenient for navigation), and a significant proportion getting wrapped in a code block which defines some cell-internal variables, I’d end up with no more than about half of my markdown cells being amenable to the new markdown mode. At that point it’s not worth the inconsistency of having two different mechanisms, especially since I already find typing md``​ easy and convenient.

I almost never make bare html template cells; those are always the returned content of a longer code block.

The buttons in the little little pop-up button bar are not useful to me, and its current placement and animation are distracting. I’d prefer the button bar to go away entirely, but it would also maybe be okay if moved to the top right of the cell editor.

Having new notebooks default to a markdown cell for the title is going to add a slight bit of extra friction for me changing it back every time.

One thing that might help is a bit more clarity from the Observablehq team about the vision / direction this kind of feature is aiming for. Is this a one-off addition, or part of some more systematic set of planned changes?


I am not super into the current feature set, its all pretty trivial and what we can do with template literals, but you can’t really do proper static analysis when your language is embedded within template literals. So I hope this is really a stepping stone towards proper static analysis (e.g. Typescipt intellisense) which would be an amazing feature long term.


Static analysis of what tho? :sweat_smile: Markdown?

Wouldn’t template literals be much more of a step into that direction, because they give you the incentive to have strong static code analysis for the ability to also perform syntax highlighting within template literals?

Or are you hoping for a typescript mode? Couldn’t regular cells just become typescript cells, due to it being a proper subset? And is that really realistic, considering the additional barrier of entry that TS provides, and observables clear distaste for anything that makes it harder for absolute beginners?

I have to agree with @somethingelseentire. I think the lack of modes was what made Observable so much nicer than the competition.


Spellcheck is a form of static analysis I would be extremely keen on.

1 Like

Interesting. It actually tickles my curiosity enough that I might start building a proof of concept for statically analysed JS with md literals.


It is neat, but it was a bit unexpected. Maybe it can be done so you can edit a cell which just has md`stuff` in it with the markdown editor.

Something I’ve done a couple of times is changing md`stuff` to { var x = some_long_expression; return md`stuff ${x}` . Is that a thing you can do with these cells?

1 Like

(My input is along the same lines as that given by @jrus, so I’m including this as a reply to their comments. I am someone who wants to create documents that integrate mathematical exposition with static and/or interactive js-driven visuals.)

I’m a wannabe observablehq user, but so far the friction to which others have alluded has been too great. One of my biggest wishes was that the markdown blocks would accommodate katex/mathjax seamlessly, as in math.stackexchange.com. I.e. use - and $$-$$ pairs whenever you want to go into math mode, and also see the rendered version in real time.

When I got the notification about tex cells my interest was piqued, but it’s a disappointment. A frictionless $$-$$ would be much better. So, sorry guys, I love the observablehq content produced by users more motivated than me, but for now I will continue to be on the sidelines.


If the current setup has too much friction you can certainly make your own TeX-in-markdown (or whatever) template literal that parses out stuff wrapped in \( ... \) or $ ... $ or whatever. The notebook platform itself doesn’t need any modification.

Here are some links to get you started:





Kelly van Evert wrote this notebook way back in 2018:

It seems to break when I try to import it though, but it’s another starting point (and I wonder if it can be simplified)

Thank you! I did a short test and it worked. I just used the line
"import {texmd} from “@kelleyvanevert/katex-within-markdown”

1 Like