Project

SvelDocs

Documentation boilerplate project for Svelte. Allows for quickly setting up a documentation website with a modern layout and search feature. Add markdown files in a pre-established structure for quickly expanding the documentation.

View Project

Introduction

SvelDocs is a template that helps you build elegant, searchable documentation sites with SvelteKit. It is open source and fully customizable, with built-in support for both server side rendering and static sites.

The Motivation

This project was developed for use with other projects, as I found myself wanting to create documentation websites for them. I needed a vast amount of features, and didn't want to pay for something like Mintlify, so the obvious next step was to build it myself.

While there are other templates for creating documentation websites, they were missing a couple things that I found important. Yes, I can customize them to solve most of the interface problems I might have, but there was one feature that none of them seemed to have - the option for server side rendering. Most documentation sites out there purely use static site generation - but what if I wanted to have different documentation for different users? This was a large reason for why SvelDocs was created.

Tech Stack

The tech stack includes Svelte, TypeScript, Tailwind CSS, and Vite. I don't typically mention Vite since every Svelte project uses them, but this one uses several vite plugins that are vital to the project, like preloading document data at build time which reduces server side computation.

Server Side Rendering

There is a reason people don't create server side documentation, and that's because its not trivial on how to do it safely. Options like mdsvex are only applicable to client side rendering, so we need a custom solution.

Challenge

Server side data must be sent over as a JSON object - that means no passing down svelte components. This is why packages like mdsvex cannot be used, as they convert markdown files into svelte components. While you can then convert svelte components into html, passing that html string to the client can result in a couple of issues.

The only way to really render this html string is to use the { @html } command in svelte - which svelte warns you not to use as it can dangerously inject scripts - and even if you don't have dangerous scripts, the other major issue is that components will not be reactive.

Solution

The solution is to convert markdown files into a HAST or HTML Abstract Syntax Tree, which is a JSON structure of all the HTML elements to use on the client. A very popular way to do this conversion is to use remark and rehype ecosystem. remark is used to convert markdown into a MDAST or Markdown Abstract Syntax Tree, which then converts to a HAST with remark-rehype.

This HAST is just pure data, so how do we render it? Well, we can send this data to the client, which can then handle the rendering by looping through the HTML elements and their children. Below is an example of a HAST structure, and we can loop through this to map the "type" to an actual svelte component if needed.

{
	"type": "element",
	"tagName": "div",
	"properties": {
		"className": ["container"]
	},
	"children": [
		{
			"type": "text",
			"value": "\n  "
		},
		{
			"type": "element",
			"tagName": "h1",
			"properties": {},
			"children": [
				{
					"type": "text",
					"value": "Hello"
				}
			]
		},
		{
			"type": "text",
			"value": "\n"
		}
	]
}

Generating this HAST can be pretty computationally expensive, especially for a lot of markdown. Having the server do this for every user that visits the page will make the site load slower - so it is obvious that we need to preload or cache the data. This is where the Vite plugins come in - when the server is built, the Vite plugins run to generate all the markdown into HASTs, and expose them as a TypeScript virtual module that is only imported into the server.

Conclusion

This project has many more features and can be viewed here.

Now that it is complete, it will be imported into my other projects to provide great looking documentation without having to do much work - other than write the markdown documenation.