Staff Software Engineer
Clojure, architecture, and engineering decisions. Based in Singapore.
How I went from a personal Claude Code setup to a plugin marketplace for a small engineering team, encoding Clojure conventions, REPL workflows, and git practices into shareable skills. I suggested our CEO adopt the Anthropic Team plan, wrote onboarding guidelines, and built the plugins that the whole team and some of our clients' developers now use daily.
How I use Claude Code as the primary interface for an Obsidian vault, capturing technical knowledge mid-session with full context, retrieving past notes to inform current work, and keeping vault conventions consistent through a custom plugin.
Using an Obsidian vault as the single source of truth for blog content. Articles live alongside the working notes that informed them, linked through wiki links. The blog site is just a renderer, markdown files are the contract, and the entire authoring workflow happens inside the vault.
A custom frontend architecture for ClojureScript SPAs using Replicant, where effects are maps, dispatch is a closure, and the state layer is pure
.cljctestable on the JVM. Used in both flybot.sg and pattern.flybot.sg.How we replaced REST routes and controller functions with a pull-pattern API where collections are nouns, patterns express intent, and authorization is structural, all built on three composable libraries from the lasagna-pattern monorepo.
A Babashka-driven approach to managing Clojure monorepos with auto-discovered components, two-layer task delegation, and consistent
deps.ednconventions. Applied to lasagna-pattern, a toolbox of 5 components spanning libraries and full-stack apps.How I migrated our Clojure app deployment from EC2 + load balancers to AWS App Runner with S3-backed storage, cutting monthly costs from ~$50 to ~$15 and eliminating most operational overhead.
flybot.sg is a full-stack Clojure web app built to demonstrate the "lasagna stack": a pull-based pattern language where the same declarative patterns handle reads, writes, authorization, and client-server transport. This article is a project overview linking to the detailed articles on each aspect.
Fun-map turns Clojure's associative data model into a dependency injection system. A system is a map, components are entries, and different environments (prod, dev, dev-with-oauth) are just
assocoperations on that map. This article shows how we use it in flybot-site to manage three runtime modes with zero conditionals inside components.Pull Playground is an interactive SPA for learning the lasagna-pull pattern DSL. Two modes: sandbox (runs entirely in the browser via SCI) and remote (sends patterns to a live server). Same UI, same pull engine, different transport.
Hibou is a configuration-driven analytics platform built on Rama. A single EDN config generates the Rama module, the API validation schemas, and the UI query forms. The platform supports two complementary module architectures: nested PStates for pre-aggregated hot-path queries, and column-based PStates for flexible ad-hoc exploration. This article covers how I got there and what I learned about where Rama fits in the analytics landscape.
My password and authentication setup: Bitwarden for generating and storing credentials, Ente Auth for 2FA codes, and printed recovery codes stored offline. My wife uses the same stack daily, which is a good sign that the setup is genuinely accessible.
A three-layer email setup (custom domains + alias service + encrypted mailbox) that isolates spam, identifies leaks, and keeps you portable across providers.
A proof of concept replacing Apache Druid + Imply with an all-Clojure analytics stack: Kafka events ingested by a Rama module, queried through a pullable API, and visualized in a custom dashboard UI. The POC proved the architecture works but revealed the need for a generic, configuration-driven platform.
How I structure testing across Clojure projects: Rich Comment Tests for internal functions,
deftestfor system boundaries, Malli validation at entry points only, embedded services for CI, and containerized services for load tests. All wrapped behindbb testandbb rctso nobody needs to remember Kaocha flags.What Git workflow is suitable for your project: trunk-based, feature branching, forking, release branching, release candidate workflow, Feature branching to develop, GitFlow
Time in programming has too many representations, and jumping between them is where bugs live. This article walks through the progression from timestamp to instant using juxt/tick, explains why zones and offsets are not the same thing, and shows the DST edge case where adding "one day" gives two different answers depending on whether you use a duration or a period.
The apex domain problem:
flybot.sgcannot use a CNAME record, but most modern hosting services (App Runner, Vercel, Netlify) only provide DNS names, not static IPs. I went from a $36/month ALB+NLB setup to a free redirect service.A step-by-step approach to porting Clojure libraries to the CLR using the MAGIC compiler, covering reader conditionals, type hints, dependency management, and building/testing with Nostrand.
I built an AI for Flybot's card games (Big Two, PDK) using Monte Carlo Tree Search. Pure MCTS turned out to be too slow for practical use, especially after compilation to .NET via MAGIC for Unity. The solution was a hybrid: domain knowledge for early game decisions, MCTS only for endgame positions with few cards remaining. The AI depends solely on a Game protocol, making it game-agnostic.
Flybot uses Unity for card game frontends and Clojure for backend logic. To share code between the two without rewriting in C#, we needed a compiler that produces .NET assemblies compatible with Unity's IL2CPP runtime. I collaborated with Ramsey Nasser, the author of the MAGIC compiler, to stabilize and optimize the toolchain. My main contributions were on the tooling side: NuGet packaging, private repo support, a CI pipeline, and the suggestion to strip compilation out of Magic.Unity and route everything through Nostrand. The result is a three-command workflow that frontend developers have been using in production for years.
A protocol-driven architecture for card game backends in Clojure, where every game implements the same
Gameprotocol and ameta-gameengine composes them recursively via EDN configuration: rounds, scoring strategies, tournaments. All games run on both JVM and CLR (Unity), and external engineers have used the stack to implement their own games.
Loic Blanchard