Hi all,
I posted a while ago about Kiln, the documentation engine I’ve been working on for the couple of months. I’ve added new features like localised static site generation and blog generation. However I wanted to post about a new feature, which is DocC support.
Problems with DocC
DocC is a good tool for extracting source comments and symbols, making sure they link correctly, and generally excellent for API documentation. However the DocC sites that are generated are not great at all. First, there’s no index page, so that’s left for you to come up with. They don’t provide a sitemap, or integrate well with search engines, making them pretty much useless for discoverability.
Then we have versioning and multiple repos. Vapor for instance, has over 40 current packages. Each one of those is its own repo so we have 40+ DocC sites and have to have some scripts to try and tie them all together. But even then, there’s no way to switch between different sites easily. And we have different versions of packages, e.g. Vapor has v4 and v5-alpha, both of which we’d like to make available. That requires yet another site and no way to integrate them or switch. DocC offers some cross-module linking but it’s hard to configure.
Which leads onto theming - the DocC site generator is very limited in how much you can change. Every DocC site looks like the same site, and not a particularly good one. There’s no easy way to integrate it into your project’s/company’s design language, provide a header and footer to link to other sites.
And finally security - the generated DocC sites, use Vue 2, which has been end of life for coming up to 3 years. It currently has a number of security vulnerabilities registered against it (15 low, 13 moderate, 1 high) that will come up with an npm audit, most that will never be fixed, which is… not great.
Fixing DocC
This isn’t a complete criticism of DocC, it just needs a bit of love to solve these issues. The good thing - DocC is actually secretly very extensible. Because it’s designed for a SPA it outputs all the content in JSON bundles for the Vue app to parse. Kiln takes these archives and ingests them so that it can render the content in a better way. This allows it to stitch together multiple versions and repos, build a comprehensive sitemap and rewrite the URLs to more user friendly URLs. And because the content is rendered wrapped in classes that you can edit and style, you can theme it however you want, lay it out how you want and bring your own header, footer, <head> etc. It’s server rendered, exposes JSON-LD data for better SEO etc.
I’ve now migrated Vapor’s API docs to use it and it’s a much better experience. You can check the site out at https://api.vapor.codes, which even includes a real homepage (so no more redirects to /documentation) that's built for you.
Vapor’s API docs are versioned, we have all versions of all packages that can be switched between (barring Vapor 5 as it requires Swift 6.4). You can easily switch between the different packages with a simple switcher and it’s all part of the same site. What’s even better is that we have a unified search experience that works across all modules from any page.
We have a custom theme so the site looks like Vapor, not like a DocC site. It fits in with the other documentation site and our other sites. It’s not an SPA, it’s a static site, which makes it lightning fast and much better for SEO. Finally, with some relatively simple configuration, we have cross-module linking working meaning clicking through to other modules is easy and seamless, no matter what module requires what version. You configure Kiln with the version links and its stitches it all together for you:
APIPackage("vapor/jwt", group: "Authentication", versions: [
PackageVersion("4", name: "4.x", ref: "v4", isDefault: true, dependencies: [
DependencyPin("vapor/vapor", "4"),
DependencyPin("vapor/jwt-kit", "4"),
], modules: [jwt]),
PackageVersion("5-beta", name: "5.0 (beta)", ref: "main", isPrerelease: true, dependencies: [
DependencyPin("vapor/jwt-kit", "5-beta"),
], modules: [jwt]),
])
In this example, JWT 4's docs link to Vapor 4 and JWT-Kit 4; JWT 5's link to JWT-Kit 5. Kiln resolves the rest of the graph itself. For the real site, when generated, pages like CommandContext · Vapor · Vapor API Docs allow you to click through to the original type or the original module, which makes a much better experience.
Hopefully this helps other maintainers make better sites!