Skip to main content

Building a docusaurus app

· 6 min read

I switched to Docusaurus in March as framework for this website. This blog summarizes my experience.

Why Docusaurus?

The dark period when this website was built with Vue is crucified for eternity in the git history of the GH pages repo.

Well, I'm not condemning Vue—it is powerful. Powerful, indeed, since you can virtually build anything off it. The school club administration system that I'm currently developing uses Vue for front-end, for example. The blame is probably on me, that I don't have much time to spare to build everything from scratch.

I initially chose Vue for three reasons, and had I begun with React, I probably would have the same arguments:

  1. I planned to showcase several of my earlier works, including Todo list and Math editor, which are both built with Vue. I can easily import them as modules if the entire website is Vue-based.
  2. I was just learning Vue-CLI at the time, and building the personal website becomes the perfect opportunity for some hands-on experience.
  3. I enjoyed have high degree of control over the page design, like where to put each component and sizing.

But problems soon emerged. To name a few:

  1. Vue is simply not the best for purely static contents. It doesn't support Markdown out-of-the-box. To build the simple blog module, I had to build each blog post as HTML components and import them one-by-one—a lot of messy code created in this process.
  2. I failed to set up auto deployment. CI constantly failed, and the official documentation didn't help much with handling CircleCI, the CI/CD app I'm using. This is not Vue's problem, but mine. I just want some paradigm that I can directly copy from, which unfortunately was not available.
  3. I don't have much experience with UI designs. The hard-coded CSS that looks good on a computer screen becomes messed up on a mobile screen. In addition, the UI framework Vuetify was too profound to work with.

In short, I want a tool that I can spend 30 minutes building something, not spending 30 days building everything. Docusaurus is good in this respect for its rapid development.

I've already built two docusaurus apps. The homepage for our Computerization club, and the homepage for the Baterock server. They had the exact same tech stack, so there indeed exists a paradigm that I can readily use.

Maybe I shouldn't have compared Vue with Docusaurus, just like one won't compare a knife to a fork, but I was simply illustrating the point of my migration to Docusaurus. It supported hosting Markdown documents, and also exposed React APIs to build other components. However, I did have to learn React since I've always worked with Vue, and the striking difference between Vue and React may be yet another topic worth reflecting on. (And that might be a holy war worth fighting. In this war I still stand with Vue.)

I still don't know if Docusaurus is the best tool to use for a personal webpage (for example, several people I know use Wordpress), but I decided to stick to what I'm familiar with. The primary purpose of Docusaurus, in fact, is to host documentation for open-source projects, hence the word "Doc"-usaurus. But it looks equally good for hosting articles and blog posts.

Building the app

I spent 500 words talking about nonsense. Now, onto some tech stuff. Initiating a Docusaurus project is just:

$ npx @docusaurus/init@latest init personal-page classic
$ yarn install
$ yarn start

And then there's lots of customization to be made. Docusaurus has dummy contents scattered everywhere, and it will take some time hunting them all down. Take a look at this commit for most of the work that needs to be done. A short checklist:

  1. Remove all pre-existing docs and blogs and add some real contents. Modify /sidebars.js as needed.
  2. Select a theme color for the page. I used #39cac4, reason given in the profile. Consult this tool for different shades, and paste them in /src/css/custom.css.
  3. Draw a logo for the webpage. Most might use the GitHub avatar or a photo, but I did draw a logo which then became my new GitHub avatar. If you wish, re-draw the feature images on the front page as well.
  4. Browse through /docusaurus.config.js line-by-line and make necessary modifications.
  5. Browse through /src/pages/index.js line-by-line and make necessary modifications.
  6. To enable TypeScript support, run yarn add @docusaurus/module-type-aliases. Then add the file to the root:
types.d.ts
/// <reference types="@docusaurus/module-type-aliases" />
  1. KaTeX\text{\KaTeX} is a must for me. Add it by running
$ yarn add rehype-katex
$ yarn add remark-math@3.0.1

and adding

/docusaurus.config.js
const remarkMath = require('remark-math');
const rehypeKatex = require('rehype-katex');

module.exports = {
title: 'Joshua Chen',

...

stylesheets: [
{
href: 'https://cdn.jsdelivr.net/npm/katex@0.12.0/dist/katex.min.css',
type: 'text/css',
integrity:
'sha384-AfEj0r4/OFrOo5t7NnNe46zW/tFgW6x/bCJG8FqQCEo3+Aro6EYUG4+cU+KJWu/X',
crossorigin: 'anonymous',
},
],
scripts: [
{
src: 'https://cdn.jsdelivr.net/npm/katex@0.12.0/dist/katex.min.js',
integrity:
'sha384-g7c+Jr9ZivxKLnZTDUhnkOnsh30B4H0rpLUpJ4jAIKs4fnJI+sEnkvrMWph2EDg4',
crossorigin: 'anonymous',
defer: true,
},
{
src: 'https://cdn.jsdelivr.net/npm/katex@0.12.0/dist/contrib/mhchem.min.js',
integrity:
'sha384-5gCAXJ0ZgozlShOzzT0OWArn7yCPGWVIvgo+BAd8NUKbCmulrJiQuCVR9cHlPHeG',
crossorigin: 'anonymous',
defer: true,
},
],
presets: [
[
'@docusaurus/preset-classic',
{
docs: {
sidebarPath: require.resolve('./sidebars.js'),
remarkPlugins: [remarkMath],
rehypePlugins: [[rehypeKatex, { strict: false }]],
},
blog: {
remarkPlugins: [remarkMath],
rehypePlugins: [[rehypeKatex, { strict: false }]],
},
theme: {
customCss: require.resolve('./src/css/custom.css'),
},
},
],
],
}

I got the inspiration from https://docs.theochu.com/docusaurus/latex/. This may not be the most elegant way to do it, but it works. Sadly, until now I've been unable to incorporate mhchem correctly, so \ce{} still fails.

Deployment

The next step I did was setting up CI/CD. The CircleCI configuration file is readily available. The only changes needed to be made are the git credentials and environment variables in deploy-gh-pages. Generate a personal access token here. Give it repo controls only and paste it into the CircleCI project settings > Environment Variables. And that's it.


Now we get a webpage already loaded with contents. The next step is to fill the /docs/ and /blog/ folders up, and writing some more pages with React. In the following posts, I plan to discuss:

  • Automating bulk file processing with bash scripts;
  • TypeScript vs JavaScript;
  • React components vs Vue components.

Every topic sounds very ambitious that I can write an epic on. I will try to make everything succint and to the point.