Personal blog built with Kotlin.
- NEVER directly edit files under
output/. Theoutput/directory is auto-generated bymake generate. Make changes intemplates/,articles/, or generator source code, then runmake generateto regenerate.
# Generate article HTML + articles.json + index.html + feed.xml + sitemap.xml → output/
make generate
# Generate only changed articles (DEV mode)
make dev
# Create a new article markdown file
make new my-article
# Build worker (Kotlin/Wasm → Wasm)
make build-worker
# Local development server (wrangler dev)
make serve
# Deploy to Cloudflare Workers (builds worker + generates articles first)
make deployGradle multi-module project (Kotlin) with generator and worker modules, deployed to Cloudflare Workers + Static Assets.
Converts articles/*.md (with YAML frontmatter) to HTML and outputs them to output/.
Pipeline: FrontmatterParser.parse() → MarkdownRenderer (commonmark) → transformers (ImageCaptionTransformer, XEmbedTransformer, GistEmbedTransformer) → TemplateEngine.render() ({{key}} replacement) → write to output/
Generator: Orchestrates HTML generation for all articles, index pages, feed, and sitemapIndexPageGenerator: Generates paginated index pages (20 articles/page)FeedGenerator: Generates Atom RSS feed (feed.xml)SitemapGenerator: Generates XML sitemap (sitemap.xml)ArticleCreator: Creates new article markdown files fromtemplates/article.mdwith current dateTemplateEngine: Regex-based{{key}}placeholder replacementFrontmatterParser: Parses----delimited YAML frontmatter with SnakeYAML Engine, returnsArticle(metadata, content, tags)AssetHasher: MD5-hashes CSS/JS files for cache busting (styles.<hash>.css,theme.<hash>.js)JsonWriter: Manually builds JSON strings without external libraries (RFC 8259 escape handling)
Kotlin/Wasm module compiled to WebAssembly that runs as a Cloudflare Worker. Handles routing, response headers (Content-Type, Cache-Control, security headers), and serves static assets via the ASSETS binding.
Worker.kt(src/wasmJsMain/kotlin/): Route resolution (sealed classRoute), asset fetching, robots.txt/sitemap.xml generation, 404 handling. Only GET requests are allowed.entry.js: JS entry point that bridges wrangler to the compiled Kotlin/Wasm (blog-worker.mjs)build.gradle.kts: Kotlin/Wasm configuration with Cloudflare Workers compatibility patches (removes Node.js/Deno detection, injects Cloudflare-specific Wasm instantiation)
Deployed via wrangler deploy. Static assets are served directly when matched (run_worker_first: false); the Worker handles routing and headers for everything else.
wrangler.jsonc: Workers project configuration (project name:mataku-com, entry:worker/entry.js, assets dir:output/)
articles/— Markdown article sources (frontmatter: title, date, tags)templates/— HTML templates (article.html,index.html,404.html),article.mdfor new articles,styles.cssandtheme.js(manually maintained)output/— Generated output (auto-generated, do not edit)worker/— Cloudflare Worker source (Kotlin/Wasm)generator/— Static site generator source (Kotlin/JVM)