CodePen as a Component Editor

When we started working on Duet Design System early last year, one of our goals was to create similar component playgrounds as I had previously built for Vue Design System. While this seemed like an obvious decision at first, we soon realized that maintaining a code editor of our own required far too much effort, especially since Duet’s documentation is a custom built platform created for a specific organization’s needs.

We figured there must be a simpler approach. Maybe all of it didn’t have to be a part of the documentation itself. The most important goal was to have a code playground which would enable quick prototyping and testing.

This got us thinking. We were already using CodePen when we needed to quickly prototype or design something in the browser. Could we utilize the same tool for the public website as well to make the component documentation more interactive?

Introducing CodePen API #

Turns out CodePen has a nice API for this which allows you to start a new Pen with code and settings that you send across programmatically. To pre-fill a Pen with your own code and options, you post a form with data in JSON format to https://codepen.io/pen/define.

A simple example looks like this, try it out by clicking the “Edit on CodePen” button:

<form action="https://codepen.io/pen/define" method="POST" target="_blank">
<input type="hidden" name="data" value='{"title": "Button", "html": "<button>Click me</button>"}' />
<input type="submit" value="Edit on CodePen" />
</form>

If you observe the example above, you might notice that I have added a hidden input inside the form. This input has the data I want to be editable set as its value:

<input
type="hidden"
name="data"
value='{
"title": "Button",
"html": "<button>Click me</button>"
}'

/>

Now, in reality, we usually want a little more than this. CodePen’s API provides a set of options you can include in the JSON. In Duet Design System, we are utilizing the following options:

<input
type="hidden"
name="data"
value='{
"title": "Generated title",
"html": "<button>Code that you want to be editable</button>",
"css_external": "url-to-stylesheet.css;url-to-stylesheet.css",
"js_external": "url-to-web-components.js"
"layout": "left",
"editors": "100"
}'

/>

With css_external option we are first of all linking to the necessary stylesheets on Duet’s content delivery network. js_external option does the same, but for JavaScript. layout and editors define what the CodePen editor itself will look like. With the above settings the code editor will live on the left side and only HTML editor will be open by default.

In case you’re using a static website generator like i.e. Eleventy or Next.js to document your design system, you could programmatically generate all of the contents for this form.

In Duet the automation works roughly so that we first generate Markdown files based on JS Doc style comments in the components. These Markdown files are then transformed using Eleventy and its templating features into user editable static webpages, by looping through all the components and adding the necessary bits programmatically:

{%- for example in examples -%}
<form action="https://codepen.io/pen/define" method="POST" target="_blank">
<input
type="hidden"
name="data"
value='{
"title": "Duet — {{ example.name | capitalize }}",
"html": "{{ example.code | safe }}",
"css_external": "{% duet_css_assets %}",
"js_external": "{% duet_component_assets %}",
"layout": "left",
"editors": "100"
}'

/>

<input type="submit" value="Edit in CodePen" />
</form>
{%- endfor -%}

Escaping quotes and new lines #

If you try to utilize the above example on your own website, you might quickly notice that it produces invalid JSON when you have e.g. ", ', or new lines in the HTML inside the JSON object. To escape all quotes in JSON, you could use something like:

const processedHtml = JSON.stringify(originalHtml)
.replace(/"/g, "&​quot;")
.replace(/'/g, "&apos;");

In case you’re using Eleventy with Nunjucks (like we are), you could instead use something like this which replaces all quotes and makes sure new lines won’t break JSON:

value='{
"html": "{{ your_html | safe | replace('"', '\\"') | replace('\'', '&#39;') | replace('\n', '\\n') }}"
}'

CodePen’s own documentation also includes clear guidelines on how to achieve this with the help of jQuery on the client side.

Conclusion #

Our industry has a tendency to over-engineer things (yes, I am guilty too), so I’m happy that we found a solution that has vastly simplified things. What’s lovely as well, is that this feature has got some of our designers to start utilizing CodePen as their tool of choice for prototyping.

Today, Duet Design System has this functionality implemented for all of its component and template examples. Take a look of the Button component for example and hit the “Edit on CodePen” button.

Tl;dr. If you have a small team and you’re looking for a simple way to have editable component examples in your design system documentation, CodePen’s API might be an option worth considering. ❦

Get in touch

I’m an independent design systems architect specialized in helping organizations to build design systems. Get in touch.

Share