Engaging your users is and will always be an essential part of statically generated sites, whether you’re dealing with developer documentation, guides, API references, or even blog posts like this one. One way to achieve this is by adding interactive and runnable code snippets to your content.
Interactive code snippets enhance the user experience of your docs, website, or any other content you’re putting out there. They allow readers to experiment with the code in real-time, make edits, implement new functionalities, execute, and see the results all while still reading your content.
Since there are many benefits of interactive code snippets, let’s discuss how to implement this feature in this post using a library called blog-cells. Jump ahead:
We’ll go over a simple demo of blog-cells in CodePen as well as a more detailed example using blog-cells with Middleman. You can interact with these examples or just jump right into this tutorial.
You may be wondering why you should bother adding interactive code snippets to your site. What benefits does it add to your current user experience and workflow? Let’s talk about it.
These are just a few of the benefits I’ve experienced with interactive code snippets, and you can likely think of others relevant to your particular use cases. Personally, I’ve always preferred interactive code examples over static ones, which may or may not work when I copy them over to my code editor.
With that covered, let’s talk about how you can add interactive code snippets to your site. There are various solutions available, but the one I found most interesting is the blog-cells library.
blog-cells is an open source library that transforms any web page into an interactive code notebook. It is written in TypeScript and runs entirely in the browser without requiring a server-side component.
You can add blog-cells to your projects via the CDN. It works with HTML websites and static site generators like Hugo, Jekyll, Middleman, and others.
Installing blog-cells is simple. You just need to add the JavaScript and CSS imports to the root HTML file of your project, just as you would with any other CDN links. You can then immediately create code cells — the interactive code snippets — with the script.
In the example below, we are adding the blog-cells JavaScript and CSS files to the root HTML file:
<!-- Import blog-cells JS and CSS files via CDN --> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/blog-cells.css" /> <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/blog-cells.js"></script>
This root HTML file could be your /public/index.html
or simply your .index.html
file depending on the way your project is set up.
With that import handled, you can now create code cells in your site like so:
<script type="text/notebook-cell"> console.log("Hello World!"); </script>
When the browser renders the page, blog-cells will transform the script
tags with the attributes of type="text/notebook-cells
into interactive and runnable code snippets like this:
The interactive and runnable part comes into play when a user experiments with the code. For instance, I can edit the cell directly and click RUN to execute it. Let’s change the code to say Hello Reader!
like so:
And just like that, we have interactive code snippets in a simple HTML project. You can test this out and interact with it yourself directly in the examples above or on CodePen to see it side-by-side with the code.
Logging stuff to the console is not exactly very helpful if that is the only thing the library does, right? But that’s not all the blog-cells library is capable of doing.
Let’s start exploring its features more by taking a look at how to use this library in Middleman, a cool static site generator with better out-of-the-box support for blog-cells.
At the moment, we have interactive code snippets working in our CodePen demo. However, as we mentioned earlier, we can also use this library in a static site generator. Let’s build a Middleman demo to showcase this capability.
Note that for some static sites that block HTML tags from appearing in the output, you might need additional configurations to get blog-cells working. For instance, when working with Hugo, you will need to open your Hugo config file and add this snippet:
[markup.goldmark.renderer] unsafe= true
This will allow blog-cells to inject the necessary HTML tags in the output of your Hugo site to provide the relevant blog-cells functionality.
To create a Middleman project, you need Ruby and RubyGems installed on your computer. For some computers — like MacBooks — these come preinstalled. You can confirm that they’re installed by running these commands in the terminal:
ruby -v gem -v
The commands above will show you the installed versions of Ruby and RubyGems on your computer. If you don’t have them, follow their respective official installation guides to install them onto your computer.
With those two packages installed, you can run the following command to install Middleman:
gem install middleman
In addition to installing Middleman, the above command will also expose native Middleman commands to your terminal. This means after successfully installing this static site generator, you can now run the following command to create a new Middleman project called myblog
:
middleman init myblog
This will create a myblog
project on your computer. Next, navigate into that project and start the development server with the following commands:
cd myblog middleman server
You should now see your Middleman project available on the browser at http://192.168.1.80:4567/
. Now that we have a Middleman project up and running, let’s add blog-cells to it.
To add the blog-cells JavaScript and CSS files to the project, open the layouts/layout.erb
file and update it with this code:
<!doctype html> <html> <head> <meta charset="utf-8"> <meta http-equiv="x-ua-compatible" content="ie=edge"> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> <!-- Use the title from a page's frontmatter if it has one --> <title><%= current_page.data.title || "Middleman" %></title> <%= stylesheet_link_tag "site" %> <%= javascript_include_tag "site" %> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/blog-cells.css" /> <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/blog-cells.js"></script> </head> <body> <%= yield %> </body> </html>
In the code above, we imported the blog-cells JavaScript and CSS files into the <head>
tag of the layout file. This makes blog-cells available throughout the project. Next, let’s create the blogpost files and add some dummy content to them.
In the /source
directory of your Middleman project, create a new articles
directory and add two files to it. We can call the files article1.html.erb
and arcticle2.html.erb
, respectively. These files will represent our individual blog posts. For each of the files, update it with this code:
--- title: Welcome to Lorem Ipsum --- <h1> What is Lorem Ipsum? </h1> <p>Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book </p> <p>This is an interactive code snippet that you can run</p> <script type="text/notebook-cell"> console.log("Hello World!"); </script> <h2>So what if I want to execute a function?</h2> <p>You can also do that with Blog-cells as you can see below</p> <p> <script type="text/notebook-cell" data-autorun="true">export function hello() { console.log("Hello World, from a function!"); } hello(); </script> </p>
In this file, we’ve added a sample blog post to showcase how we can add interactive code snippets into a Middleman blog post. All we need to do now is update the homepage with a link to these two posts.
To do that, open the /source/index.html.erb
file and update it with this code:
--- title: Welcome to my Blog --- <h1> Click to read posts </h1> <%= link_to( "Read Article 1", "/articles/article1.html", ) %> <%= link_to( "Read Article 2", "/articles/article2.html", ) %>
Here, we’ve provided links to both our blog posts. Now, when we run the project, users should be able to click any of the links to navigate to the post. The important thing to note is that you can directly add the blog-cells scripts into the post, and it will render a runnable snippet:
Now that we have interactive code snippets working in the Middleman SSG, let’s talk about some other blog-cells features you should know.
There are tons of interesting ways to use blog-cells to incorporate interactive code snippets into a website. Here are a few ideas:
await
syntax in your functionslog
, error
, warn
, and assert
data-kernel="python"
attribute to the script.data-autorun=true
attribute to the scriptThese capabilities should give you some ideas for how to leverage interactive code snippets in your project.
Keep in mind that blog-cells is an open source project maintained by a single contributor, so you should not expect a frequent rollout of new features or dedicated support. This also means resources are limited, so you won’t find many example implementations or guides outside the documentation.
Additionally, this library doesn’t work out of the box with any static site generator that blocks the injection of HTML tags into its final HTML output.
Lastly, blog-cells allows you to extend your codebase. As a result, if you write a lot of functions to run in your interactive code snippets, those functions will count towards the size of your entire project.
In this post, we covered the basic principles of the blog-cells library. We went over the importance of interactive code snippets and how blog-cells helps implement this feature into both native HTML projects and static site generators.
There is a lot more you can do with blog-cells beyond what we demonstrated in this tutorial. I hope you give it a try and give your users a better experience. You can access the live demo of the project we built or check out the full project code on GitHub.
LogRocket is a frontend application monitoring solution that lets you replay problems as if they happened in your own browser. Instead of guessing why errors happen or asking users for screenshots and log dumps, LogRocket lets you replay the session to quickly understand what went wrong. It works perfectly with any app, regardless of framework, and has plugins to log additional context from Redux, Vuex, and @ngrx/store.
In addition to logging Redux actions and state, LogRocket records console logs, JavaScript errors, stacktraces, network requests/responses with headers + bodies, browser metadata, and custom logs. It also instruments the DOM to record the HTML and CSS on the page, recreating pixel-perfect videos of even the most complex single-page and mobile apps.
Would you be interested in joining LogRocket's developer community?
Join LogRocket’s Content Advisory Board. You’ll help inform the type of content we create and get access to exclusive meetups, social accreditation, and swag.
Sign up nowAngular’s two-way data binding has evolved with signals, offering improved performance, simpler syntax, and better type inference.
Fix sticky positioning issues in CSS, from missing offsets to overflow conflicts in flex, grid, and container height constraints.
From basic syntax and advanced techniques to practical applications and error handling, here’s how to use node-cron.
The Angular tree view can be hard to get right, but once you understand it, it can be quite a powerful visual representation.