Convert Excalidraw Diagram to a React Component
The goal is to extract a diagram from Excalidraw in the SVG format, to then take this SVG and convert into a React component that is interactive. This will create a more engaging "About Me" section for my personal website while highlighting my full career timeline and accomplishments.
It's easy to extract the SVG from Excalidraw, simply select the content you want to export, right click and "copy to clipboard as SVG".
I want to be able to paste that exported SVG into the textarea at the bottom of this page, click the Convert button and export a React compliant SVG that I can paste inside a React component.
The benefit of automating a lot of the conversion from Excalidraw to React is that if I have to edit this diagram in the future the process will be relatively quick and painless. I also have multiple variations of the diagram based on screen sizes.

The SVG exported by Excalidraw is not compatible with my goals within React for a few reasons:
- The SVG contains font face information for fetching the Excali web font, this is not required as I install the font directly and apply it via tailwind
- The SVG contains lots of needless information that can be removed without any impact (svg-source, metadata, defs, inline styles)
- HTML attributes on the SVG are in kebab-case and not camelCase
- The SVG size is specific to the exact width and height within Excalidraw, we want to make the SVG fit the size of it's container
- There is no logical element surrounding each box containing text, we need this container to handle interactivity
- I want to apply some of my personal styling to the arrows and rectangles
- I want a cursor pointer effect on hover of a rectangle to imply a user can click within the rectangle
- The SVG has no interactivity - no opportunity to expand a section to learn more, clicking a section should open a modal
- It is not possible for a keyboard user to tab between and select individual sections
Some Assumptions
- All rectangles and arrows in the SVG are always found with the selector
svg > g > path - As long as the text is created directly after the rectangle the text will be found in the sibling group of the rectangle. The selector is
(svg > g > path).parentElement + g. The first group element is for the rectangle and the second group element is for the text. - With these 2 assumptions we can select all our rectangle paths, all our arrow paths, all our text, correctly identify what text is found within a rectangle.
Known Limitations
Much of the implementation relies on string find-and-replace operations. For example, converting kebab-case attributes to camelCase involves searching the entire string for instances of kebab-case and replacing them with their camelCase equivalents. There is no discrimination between whether the text, such as stroke-width, is being used as an attribute in an SVG element or is part of the visible text content that should remain unchanged. Therefore we could inadvertently alter the text content, for my situation I know this will not occur and the solution is practical.
There is also a reliance on the external package cheerio. We are working with a string that represents an SVG and trying to transform it into a new format that better suits our use case. While find-and-replace was a valid solution for many of our requirements, in some cases we need to add attributes or leverage the DOM structure of the SVG. Cheerio allows us to parse the string into a format that lets us use jQuery-style selectors to modify the SVG as if it were a DOM element. Once our transformations are complete, we convert the object back into a string representation of the SVG.
Input
Input Controls
Remove defs
Remove the def SVG element and all of its inner content.
Remove metadata
Remove the metadata SVG element and all of its inner content.
Remove inline styles
Remove the styles attribute from all elements within the SVG.
Make the SVG full width
Select the SVG element and set the width to 100% and height to auto.
Remove inline font family
Select all elements and remove the font-family attribute.
Remove comments
Select all comments and remove the node.
Convert kebab-case HTML attributes to camelCase
Replace kebab-case attributes with camelCase equivalents, i.e. stroke-linecap with strokeLinecap.
Ensure text is encoded to be HTML compliant
convert text such as > to >
Make the background transparent
Class Value To Apply to the SVG container
Stroke color to apply to arrows and boxes
Stroke width to apply to arrows and boxes
Add hover rectangles to boxes and make text clickable
1Converted SVG will appear here after clicking the button.