Make Roam for Your Mind: Ode to Customization

Last update: 25th December 2020

Ode to Customisation, based on this icon.

In the previous post, I have described what makes me sometimes upset about Roam Research: the number of unfinished features and lack of polish. I formulated it strongly and it led to fascinating discussions on Twitter with some great reactions from Conor and others.

But this is just one side of the coin. At the same time, Roam has opened up extraordinary creative spaces for me and other people. This is a new kind of product that is doing things in its own way. In this story I’d like to focus on some of those creative possibilities and why I like Roam so much and why I am so passionate about it.

If you look at the public Roam-tricks database (so-called “graph”), you will notice one astonishing thing: there is an unbelievable number of various modifications, custom CSS styles, browser extensions and JavaScript plugins. All developed in free time and for free in just a couple of months. This is, without doubt, one of the largest assets of Roam. But why are there so many?

There are definitely multiple reasons for that. This time, I would like to look at just one of them: Roam in its core offers all you need to create a full-fledge copy of the internet. Do you think I am kidding? Look at this page:

This is created wholly in Roam, including the so-called “hero image”. In Roam, you can insert HTML elements, modify their appearance with CSS, and even add interactivity with JavaScript. And you can do all these three things within Roam without using any special extensions like Stylus (for custom CSS) or Tampermonkey (for custom JavaScript). These are built-in capabilities — which are also building blocks of our current World Wide Web.


The implementation of HTML is probably the weirdest one. A very limited set of HTML elements can be created directly in Roam just by writing a specific shortcode, like {{button}} creates a button, {{slider}} creates a slider, {{or: one | two | three}} creates a dropdown list.

{{button}}, {{slider}} and {{or: one | two | three }} (i.e. a droplist) in Roam
{{button}}, {{slider}} and {{or: one | two | three }} (i.e. a droplist) in Roam
{{button}}, {{slider}} and {{or: one | two | three }} (i.e. a droplist) in Roam

For full capabilities, however, it is necessary to use the so-called :hiccup syntax. Hiccup is a library used in the programming language Clojure for the representation of HTML. This makes sense because Clojure is also the programming language upon which Roam has been built.

For the users, it means, however, that they have to learn how to translate standard HTML into a slightly different form. So instead of writing, e.g.,<b>bold text</b>, one has to write :hiccup[:b "bold text"] . This gets more complicated as we add multiple elements with attributes and styling. However, luckily, there is a handy conversion tool, if you want to try it and you know some basics of HTML. The second issue with :hiccup is that it is currently not possible to mix :hiccup elements with standard parts of Roam within one outline/bullet point. Having said this, I believe it is a very promising part of Roam with — hopefully — great future, even though it is rather rarely used right now.


CSS implementation is probably the most elegant one and the easiest to use from technological trinity. Today, there is a special Roam page in every database with the title roam/css where one can simply create a “code block” and add styles that will apply to the whole website. What is elegant about this solution, is that it is natively integrated into the main outlining feature of Roam, so one can use, e.g., outlining for headlines or comments.

Example of nesting CSS for … nested tags ;)

The possibilities of CSS are immense. Look at my beautiful Christmas theme (ehm ;):

My beautiful Christmas theme /s

Or maybe better, check some really nice themes collected by Anne-Laure Le Cunff, like this one by Azlen Elza:

Zenith theme by Azlen Elza with the commentary by Anne-Laure Le Cunff


Finally, there is JavaScript. Probably the most controversial and most powerful from the three and the one with the brightest future. It was first used as a hack, being injected by an insecure iframe element created (guess it) by :hiccup . This allowed running any JavaScript code even on a public Roam databases, thus possibly exposing users to hackers. At the same time, it also gave the people in the community the first taste of new amazing possibilities.

To immense credit to Roam Research, the people behind it were able to find a way to (hopefully) safely run custom JavaScript. Again, there is wonderful effort to integrate this scripting capability into the native outlining feature of Roam. One creates an outline with {{[[roam/js]]}}. The code blocks under this outline are being treated as a runnable code. However, before the code runs, it has to be explicitly allowed by the user — this strikes the balance between security and freedom.

As a result, since the introduction of roam/js, there is a visible shift in the customization community away from creating new standalone extensions towards these proto-plugins with the hope that soon there will be a full plugin system.

Roam research is not the first to do this. Check especially the little known and its beautiful precursor called Scrapbox with a very similar approach, providing even custom API for the user interface. However, the seamless combination of outlining and coding seems to be the special strength of Roam.

To demonstrate this, it is perfectly possible and fine to put different parts of code into different outlines and nest them, like this:

Nested JavaScript in Roam Research.
Nested JavaScript in Roam Research.
Nested JavaScript in Roam Research

Such an example may not seem so useful at first sight, however, this also means that outlines may be used, e.g, for comments and headlines, making code much more readable than in the standard coding editor.

The following example is from my experimental plugin called “Hyporoam”. It uses API to get the number of annotations from corresponding to pages in Roam. As you can see, I was able to put specific parts of the code under various bullet points. This means I can simply collapse them, or I can even reuse them elsewhere if I wish.

Example of using headlines in nested JavaScript in Roam Research.
Example of using headlines in nested JavaScript in Roam Research.
Using headlines in nested JavaScript

In this form, Roam starts to not only resemble IDE (integrated development environment) but it enables literate programming. In my view, it slowly starts to resemble one of the most advanced editors in this field: Leo Editor — but is much more accessible for an average user.

Leo Editor mixes seamlessly outlining and programming, source of the image.

There are just a couple of things that would make JavaScript implementation even better: It would be great to have an ability to restrict JavaScript so that it affects only outlines under itself or on a single page (can be done with workaround). We could also be able to embed snippets or functions in one code from another (can be partially done with a workaround). Finally, there could be an export of the code (incl. all nested parts) outside Roam for the use in other applications and projects. These things (together with the autocomplete and better performance in large code blocks) would make Roam real and powerful IDE.

The amazing thing about Roam is, that all these three technologies can mix! E.g., both :hiccup and JavaScript can be used to load external CSS, CSS can modify the appearance of :hiccup HTML elements, :hiccup HTML elements may be used as input for JavaScript etc. There is currently only one thing missing: a full-fledged API, that would allow plugins to modify the content of Roam (connection to external APIs is already possible).

However, this is only a part of the story. The presence of :hiccup, roam/css and roam/js do neither explain the origins of the modifications, nor how the code itself is so inviting for anyone to hack it and customize it. This will be the topic of my next story.

If you like my work, follow me on Twitter, check the public Roam database Roam-tricks, my personal public collection of my hacks, and yes, you can support me through PayPal or Patreon (I would very appreciate it). And remember: If it looks like a duck, if it writes like a duck, it is probably me.

Just a humble Roaman duck.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store