Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

ย 

History

409 Commits
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

bock

A small personal Markdown and git-powered wiki I wrote to teach myself Go. You can see it in action here.

I have old Node and Python versions of this as well for giggles.

Usage

See the releases page for a few pre-built binaries.

Here's how you can run this from source or with the binary respectively:

# --- From Source ---
git clone https://github.com/afreeorange/bock.git
cd bock

# Build mode: generate a static wiki
go run --tags "fts5" . build --in=/path/to/repo --out=/path/to/output

# Serve mode: build + live-reload dev server for local writing and development
go run --tags "fts5" . serve --in=/path/to/repo --out=/path/to/output

# --- Using the pre-built binary ---
bock build --in=/path/to/repo --out=/path/to/output
bock serve --in=/path/to/repo --out=/path/to/output

Add --help to see all options.

Commands

build

One-shot static site generation. Reads a git repository of Markdown files, renders everything to HTML, and exits.

bock build --in=<path> --out=<path> [options]

Options:

  • --in=<path> โ€” Path to article repository (required)
  • --out=<path> โ€” Output directory (required)
  • --with-json-files โ€” Generate JSON alongside HTML
  • --with-raw-markdown-files โ€” Generate raw markdown source files
  • --without-revisions โ€” Skip git history (much faster)
  • --using-disk-fs โ€” Use on-disk git instead of in-memory clone

serve

Builds the wiki and starts a dev server with WebSocket-based live reload. Revisions are always skipped in serve mode for speed.

bock serve --in=<path> --out=<path> [options]

Additional options:

  • --port=<number> โ€” Port to serve on (default 8080)
  • --theme=<path> โ€” Theme directory on disk (defaults to ./theme/ if present.)

The server watches both the article repository and the theme directory. When files change:

  • Article changes (.md files) โ€” incrementally rebuild that article only
  • Theme template changes (.tsx) โ€” re-compile the engine and re-render all pages concurrently
  • Static asset changes (static/{css,js,img}) โ€” copy to output without re-rendering

What It Does

The build command generates the following (using this article as an example):

Terminology and Setup

An Entity is either

  • An Article, a Markdown file ending in .md somewhere in your article repository, or
  • A Folder, which is exactly what you think it is. You can organize your articles into folders at any depth.
  • A Revision, which is a git commit that modifies an Article.

Other stuff:

  • The name of the Markdown file is the title of the article and will be served at a simplified URI with underscores. For example,
    • /Notes on Photography.md will be served at /Notes_on_Photography
    • /Tech Stuff/OpenBSD/pf Notes.md will be served at /Tech_Stuff/OpenBSD/pf_Notes
  • The root of the generated wiki will always redirect to /Home (for now) so you will need a Home.md.
    • You'll be warned if you don't have one.
    • It will be generated if you don't have one.
  • The paths raw, revisions, random, and archive are reserved. So, for example, don't create a raw.md anywhere. It will be overwritten.
  • You can place static assets in __assets in your article repository. You can reference all assets in there in your Markdown files prefixed with /assets (e.g. __assets/some-file.jpg โ†’ /assets/some-file.jpg). Here's an example.
  • Any dotfiles or dotfolders are ignored when generating the entity-tree.
    • This includes node_modules. See this file for other things. It's a small list.

Development

TSX Templating

All page templates and components live in theme/ as TSX and other files. Here's the required stucture (TODO: enforce this.)

theme/
  pages/         # Page templates (one per route type)
  components/    # Shared components (Base, Nav, Footer, etc.)
  static/        # CSS, JS, images served as-is
  tsconfig.json  # IDE type checking via Preact
  globals.d.ts   # Types for Article, Revision, etc.

Templates are pure function components โ€” no hooks, no state, no lifecycle methods. They are compiled at startup by ESBuild (via Go's ESBuild API) and rendered server-side in goja (a Go JS runtime) using Preact + preact-render-to-string.

Two helper functions are injected as globals:

  • formatDate(isoString, goLayout) โ€” formats an ISO date using Go's time layout syntax
  • humanizeNumber(n) โ€” formats a number with commas (e.g. 1,234,567)

NOTE: Run the build first and then serve for complete theme development.

Note on the Preact Runtime

The Preact runtime is pre-bundled at tsx/preact.js and embedded into the binary via go:embed. To rebuild it (e.g. after upgrading Preact), install preact and preact-render-to-string via NPM, then bundle with esbuild:

npm init
npm i preact preact-render-to-string

cat > tsx/preact-entry.js <<EOF
import { h, Fragment } from "preact";
import { renderToString } from "preact-render-to-string";

export { h, Fragment, renderToString };
EOF

npx esbuild tsx/preact-entry.js \
  --bundle \
  --format=iife \
  --global-name=__preact \
  --target=es2015 \
  --platform=neutral \
  --outfile=tsx/preact.js

echo 'var h=__preact.h,Fragment=__preact.Fragment,renderToString=__preact.renderToString;' > tsx/preact.js

Files

main.go           CLI: parse flags, dispatch to build/serve
build.go          Build orchestration, serve mode, re-render logic
renderers.go      Markdown (goldmark) + TSX (Preact/goja) rendering
writers.go        File and database output

tsx/
  engine.go       Compiles TSX via esbuild, renders via goja
  engine_test.go  Unit tests for the rendering engine
  preact.js       Bundled Preact runtime (go:embed-ed into binary)
  preact-entry.js Entry file for rebuilding preact.js (not bundled)

server/
  server.go       HTTP server, WebSocket hub, fsnotify file watcher
  reload.js       Client-side script: reconnects + reloads on message

Development with TailwindCSS

npx @tailwindcss/cli \
  -i ./theme/static/css/main.css \
  -o ./theme/static/css/styles.css \
  --watch

If it's just CSS editing:

npx @tailwindcss/cli \
  -i ./theme/static/css/main.css \
  -o ~/Programming/wiki.nikhil.io.articles/build/css/styles.css \
  --watch

# And then
cd Programming/wiki.nikhil.io.articles/build
lr-http-server

About

A small Markdown-based personal wiki in Go ๐Ÿบ

Topics

Resources

Stars

Watchers

Forks

Releases

Used by

Contributors

Languages