Documentation Website

Can I make something better than Google Docs?

Jan 22, 2026 Update: Jan 22, 2026 1866 Words

I’ve been trying to be better about documenting in-house game dev processes, especially technical art workflows. They tend to contain many, many discrete steps between different programs and are very easy to forget. As the company grows I find documentation becoming more and more valuable.

Trouble is, so far I’ve been just making random Google documents for these processes. This… is not ideal.

  • Over-reliance on Google
  • Terrible formatting / no interlinking documents
  • More or less non-portable
  • People forget to read them, or have no idea documentation even exists

I think I’d like to try my hand at building a website to handle the documentation. There are a number of services I could use of course, but generally I’d like to avoid anything that requires a sign-up for rug-pull reasons. Let’s see what we got.

  • Just use Hugo bro
    • Yeah, theoretically, Hugo would work just fine. Markdown is an excellent way to create pages, and I could build functionality into the site myself. Users could make and edit .md files and submit them using P4, which we already use for Unreal.
    • First problem I see is the static nature of Hugo. If a user submits a new .md file, who is gonna build the site? I could go all the way and set up some sort of auto build solutions. Jenkins, or whatever? Gets a bit complicated.
    • Is there a dynamic version of Hugo? You know, something that auto updates? Hmm.
      • Ok, the term is “Continuous Deployment”, essentially building and deploying the site whenever a Git hook is triggered. https://www.devonmorris.dev/posts/hugo-cd/#fn:1 Looks pretty straight forward - could this work with P4?
      • Getting a vps to read P4 events could be way out of scope… or maybe not so bad. -Ok, uh, apparently there is a first party p4 - git connector???
    • Technically, the docs could be 100% local lol.

UPDATE: OK, revisiting this after getting whitelotusinteractive.com online and cutting my teeth on Hugo. We could host on github and deploying on cloudflare is free and fast, and should be able to setup a subdomain easily. I don’t know if I can password protect it (could with Pangolin).

Authoring

  • Hugo is a bit complicated and relies on git / github, requiring an account per editor.
    • P4 git connector is too confusing / flimsy. In theory it would work great for keeping things easy but man that would be rough to setup, and risk fucking up our production.
    • It looks like it would be possible to sync with Google Drive, but it looks fairly complicated. I also kinda want to start moving away from using drive (this docs page is part of that!)
    • Any dynamic solution requires authentication, which is out of scope.
    • I have this problem with the WLI blog as well.
  • I could relatively simply convert google docs to .md and manually post them myself.
  • Ohhhh you can edit directly on github.com! That may be simple enough! Still need a login but that is doable. Wouldn’t support adding images. Hmm. I may stick with github and eat the fact that for now I’ll be the only contributor. I think 99% of the docs written so far are from me anyways.

Is there a nice theme to use? I probably should try that so I can learn more.

  • https://www.docsy.dev This is nice but probably a bit overkill. I also would prefer to stick with bulma vs bootstrap

Actual features I need:

  • Side bar categories / articles menu
    • Something line Content Authoring -> VAT, Vertex Paint ETC
    • Prob don’t need the right side “on this page” view, but would be cool
    • Hugo has some sort of menu code built in, learn that
  • Link to view page source / edit link on github
  • Breadcrumb at top of page
  • index pages for categories (I think this is built in)
  • Bulma “Alerts” shortcode would be nice
  • I don’t think I care about taxonomy yet, though it might be nice to learn
    • It looks pretty sick though.
  • Don’t think I need search

Do I want to pay the troll toll and figure out how to make these features into a theme? Would that even be portable? With three discrete projects running on a similar codebase things are starting to look a bit damp.

Yeah I think I’ll roll my own, once again. Perhaps I’ll start this on the linux lappy, if that works.

UPDATE: 2/27


I’m working on this - Hugo, rolling my own, etc. I started with what I hope is the hardest part - the nested side bar.

Hugo offers many nice things but is apparently not well setup for my requirements:

  • Sidebar menu
  • Nice looking / spaced list entries
  • Collapsible lists
  • Nested categories based on file structure

Style and “Details”


Sidebar styling was easy - all I had to do was set the “baseof” page to start with a column class, then call the partial, which contains a column with some rules. No problem.

Next was largely straightforward as well. Bulma provides a “menu” class that seemingly is well setup for this task. EZ.

OK, collapsible lists is where I started having trouble. After fucking around with JS for a while and hating it, I stumbled upon HTML5’s “details”. This this is seemingly dead simple - wrap your code in <details>, add a <summery> and away you go. Theoretically you get a carat automatically, and all is swell.

<ul class="menu-list">
    <li><a>Team Settings</a></li>
    <li>
        <details>
            <summary><a>Manage Your Team</a></summary>
            <ul>
                <li><a>Members</a></li>
                <li><a>Plugins</a></li>
                <li><a>Add a member</a></li>
            </ul>
        </details>
    </li>

Trouble is, bulma does NOT play nice with this. If I added the code as intended, the summery would not render as a “menu-list”, or rather it would try to render on a different line? Super annoying, and frankly I had no idea what was going on or how to debug it. After fucking around with it for a while I ultimately ended up doing probably something bad - I shifted the CSS position of the carat manually:

.menu-list summary {
  margin-left: 21px;
  margin-bottom: 10px;
  cursor: pointer;
  display: block;
  position: relative;
}

.menu-list details>summary::after {
  margin-left: -8px;
  margin-top: -30px;
  display: block;
  content: '▶';
  transition: 0.2s;
}

.menu-list details[open]>summary::after {
  margin-left: -8px;
  margin-top: -30px;
  display: block;
  content: '▼';
  transition: 0.2s;
}

This is super stupid, but it works. The carat now looks in line with the list element but actually lives above it. Dude I dunno.

Nested List


Ok, time for the garbage. I’m just going to post my functional partial code first then talk about it:

<aside class="column is-narrow is-fullheight section is-hidden-mobile">
<aside class="menu" style="width: 220px">
    {{ $currentPage := . }}

{{ $home := .Site.GetPage "/docs"}}

    <ul class="menu-list">
        <a href="/" class="menu-label">Lunos Docs</a>
        <hr>
        {{ template "section-tree-nav" (dict "context" $home "base" $currentPage) }}
    </ul>
</aside>
</aside>

{{ define "section-tree-nav" }}
{{ $base := .base }}
{{ $currentPage := .context }}
    {{ range $index, $element := $currentPage.Sections.ByWeight }}
        <li>
            <details 
            {{ range $base.Ancestors}}
                {{if eq . $element}} open
                {{ end }}
            {{ end }}
            >
            <summary>
            <!--
            <a href="{{ .RelPermalink }}">{{ $element.Title }}</a>
            -->
            <a style="color: var(--bulma-primary)">{{ $element.Title }}</a>

            </summary>
            <ul>
                {{ range $element.Pages }}
                    {{ $currentClass := ""}}
                    {{ if eq . $base }}
                        {{ $currentClass = "is-active"}}
                    {{ end }}
                    {{ if eq .Kind "page" }}                   
                        <li><a href="{{ .RelPermalink }}" class="{{ $currentClass }}"> {{ .Title }}</a></li>
                    {{ else }}
                        {{ template "section-tree-nav" (dict "context" $element "base" $base) }}
                    {{ end }}
                {{ end }}
            </ul>
            </details>
        </li>
    
    {{ end }}
{{ end }}

Yeah dude, this SUCKED to work on. At first I hoped there would be some built in magic hugo thing for this. After all, a filesystem based menu seems like the most likely simple approach one would want (put child sections in folders, auto do the thing.) There is one crummy auto tool that sorta does that but doesn’t support nesting. Useless.

At first I tried to approach this the “hugo” way by using the menu template stuff. Yeah, that just kinda didn’t work? Regardless of if I could even get it to work right it is a completely manual setup, requiring each “front matter” page to be specifically defined (like setting “parent” in front matter manually PER PAGE. Fuck that.)

I found plenty of people online looking to have a file system based menu but no concrete tutorials. There were a couple of themes that claimed it worked, but after looking at the source files I couldn’t make heads and tails of it. Dude, “Go”, the language, at least within Hu(Go) is rough to read, especially coming from a c background. What do you mean there are no delimiters in, like, anything? How the fuck do you add arguments to a function? Wait, a function is called a template? Is that a go thing, or a hugo? Why is everything called a template? Why does no one comment their hugo code??? GAHHHH.

I eventually slogged through it and go some basic results. In order to do a nested tree I knew I needed a recursive function, which is possible in hugo. The annoying thing is once you start down the recursion line you lose scope - thus making a comparision against the current page difficult. It took me WAY too long to figure out how to send along arguments to the “block template” (I think that is what it is called?) - this garbage: {{ template "section-tree-nav" (dict "context" $home "base" $currentPage) }} What do you mean I have to declare a full on dictionary to add an argument? Where in the docs does it tell you how to do this, or best practice?

Anyways, in pseudo code the "section-tree-nav" “template” loops through all pages under /docs, wraps them in details, sets it to open if it is an ancestor of the current page, then recursively loops through any pages under that page.

Content


Alright, time to start populating this thing. We have a pile of google docs with lots of good info, some formatting and images, and some deprecated stuff. I figure I’ll start by copying them over. Google docs have a convenient “Copy as markdown” option, which helps, but the image links are COMICALLY long - like 400 lines long or something. I didn’t expect the images to copy over or anything, but damn the length actually makes it pretty annoying to deal with. Fortunately copying the images themselves isn’t too bad. You have to double click the embedded docs image, then hold shift and right click. This gives you the regular “copy image” dropdown, which dumps it to the clipboard. VS supports pasting images directly into markdown, which copies the image into the current folder and makes an image tag. Perf.

I’m currently using the blog image code I made earlier, but I’ll likely want to explore some different formatting options for these. Gonna focus on data entry first, then formatting.

TODO:

  • Side bar order (weighting?)
  • Image formatting. Not sure what I want here yet, but I’m sure I can improve it somewhat. Comparison image support or at least side by side would be nice
  • Actually go through a single article and format it up.
  • Make articles for obvious missing entries
  • Intro / onboarding overview articles
  • Homepage
  • Clean up top bar
  • Host it (Cloudflare?)
  • How to edit document