RSSAmplifier

Blog

Loic Blanchard - Blog Feed

All blog articles

loicb.devRSS feed ↗26 posts

Latest posts

Drift Checks for a Self-Hosting Compiler

[MAGIC](https://github.com/flybot-sg/magic) is a compiler. It turns Clojure into .NET so Clojure can run in Unity, even on iOS. To do its job, it commits some of its build outputs straight into the repo, including the compiler's own compiled files. Those files can quietly fall out of sync with their source, and a normal build never notices. This post is about the small CI check that catches that,…

Making Magic stable

MAGIC (Morgan And Grand Iron Clojure) compiles Clojure to .NET so we can run it in Unity, including on iOS. [Ramsey Nasser](https://nas.sr/about/) built it and maintained it almost single-handedly for close to a decade. With his time for it now limited, I set out to make it dependable: I consolidated his six repositories into one Flybot-owned monorepo, built the tooling and CI it lacked, and used…

Dotfiles with Chezmoi and Age

My macOS environment lives in a single git repo managed by [chezmoi](https://www.chezmoi.io/), with secrets encrypted at rest using [age](https://github.com/FiloSottile/age). Bootstrapping a new machine is one script and one manual step: restoring the age key. I started with the Bitwarden CLI feeding chezmoi's secret templates, then migrated to age. The April 2026 Bitwarden CLI supply chain attack…

Clojure Protocols and the Decorator Pattern

How `defprotocol`, `defrecord`, `deftype`, and `reify` compose into a decorator pattern, taught through a real [collection library](https://github.com/flybot-sg/lasagna-pattern/tree/main/collection): implement the interfaces behind Clojure's built-in verbs once, so a database-backed type behaves like native Clojure data, then give each user role a thin wrapper that overrides only the behavior it…

From Functions to Data - Evolving a Pull-Pattern API

How a pull-pattern API evolved from function-calling patterns to structural data matching, and what the shift from verbs to nouns taught us about API design in Clojure.

Building Claude Code Plugins for the Team

Claude Code wrote working Clojure that did not look like ours. So I encoded our conventions, REPL workflow, and git practices into Claude Code skills, bundled them into plugins, and published them as a marketplace the whole team installs from our private GitLab. I keep a second, personal marketplace on a private GitHub repo for the workflows that are only mine. This is how the two fit together,…

Claude Code and Obsidian for Note-Taking

How I use Claude Code as the main interface to an Obsidian vault: capturing well-linked notes without leaving the session, while the context is still live, then generating team sprint reports and blog articles from those same notes. Nested `CLAUDE.md` files give each directory (public, company, private) its own rulebook, so every output comes out in the right style.

Obsidian Vault as Blog Source

My Obsidian vault is the single source of truth for my blog [loicb.dev](https://www.loicb.dev): articles live next to the working notes that informed them, and the website ([open source](https://github.com/skydread1/me)) is just a renderer. Frontmatter is the schema, the TLDR section becomes the home page preview and the RSS description, and mermaid diagrams render in Obsidian while writing and on…

Building a ClojureScript SPA with Replicant and dispatch-of

A small architecture for ClojureScript single-page apps that diverges from [Replicant](https://github.com/cjohansen/replicant)'s recommended data-events dispatch: effects are plain maps, `dispatch!` is a single closure components call directly, and the state layer is pure `.cljc` you can test on the JVM. It runs the [flybot.sg](https://www.flybot.sg) site, the interactive…

Building a Pure Data API with Lasagna Pattern

How [flybot.sg](https://www.flybot.sg) replaces REST routes and controller functions with a single pull-based API: collections are nouns, EDN patterns say what the client wants, and the shape of the data decides who can see what. It is built on three small Clojure libraries, `pattern`, `collection`, and `remote`, from the [lasagna-pattern](https://github.com/flybot-sg/lasagna-pattern) monorepo.

Clojure Monorepo with Babashka

A [Babashka](https://babashka.org/)-driven way to run a Clojure monorepo: each component owns its `deps.edn`, and a root task runner auto-discovers components, delegates to per-component overrides, and shares one convention for aliases and deploys. Applied to [lasagna-pattern](https://github.com/flybot-sg/lasagna-pattern), a toolbox of five components spanning libraries and full-stack apps.

Deploying a Clojure App to AWS with App Runner

How I migrated the flybot.sg deployment from EC2 with two load balancers to [AWS App Runner](https://aws.amazon.com/apprunner/) with S3-backed Datahike, cutting the bill from about $50 to about $15 a month and removing most of the operational work.

Flybot.sg - A Full-Stack Clojure Web App

[flybot.sg](https://www.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 the project overview, with links to the detailed articles on each part of the stack.

Managing Web App Modes with Fun-Map in Clojure

[Fun-map](https://github.com/robertluo/fun-map) turns a Clojure map into an associative dependency injection system: the system is a map, components are entries, and each runtime mode is an `assoc` (or `dissoc`) on the base map. This article grows a minimal blog API with Datahike and http-kit from hardcoded values to three modes (prod, dev, test) with no mode conditional inside any component, and…

Pull Playground - Interactive Pattern Learning

[Pull Playground](https://pattern.flybot.sg) is an interactive SPA for learning the [lasagna-pattern](https://github.com/flybot-sg/lasagna-pattern) pull DSL. Sandbox mode evaluates patterns entirely in the browser with SCI against an in-memory store, and remote mode sends the same Transit-encoded patterns to a live server. One UI, one pull engine, two transports.

Hibou - An Attempt at a Generic Analytics Platform with Rama

Hibou is a configuration-driven analytics platform built on [Rama](https://redplanetlabs.com/learn-rama), generified from our gaming stats POC. A single annotated EDN config generates the Rama module, the API validation schemas, and the UI query forms, so adding analytics for a new event schema is a config file, not a development project. This article covers the architecture, the…

Password Security - Managers and Two-Factor Authentication

My password and authentication setup: Bitwarden generates and stores a unique password per account, Ente Auth holds the 2FA codes with end-to-end encrypted backups, and printed recovery codes stay offline at home. The whole stack is free, works on every platform, and once set up, logging in is faster than typing a password from memory.

Email Privacy with Custom Domains and Aliases

A three-layer email setup (custom domains, an alias service, an encrypted mailbox) that makes spam traceable to the service that leaked your address, containable by disabling a single alias, and portable across providers with a DNS update.

Gaming Stats Aggregation with Rama

A proof of concept for replacing Apache Druid + Imply with an all-Clojure analytics stack: Kafka events pre-aggregated by a [Rama](https://redplanetlabs.com/learn-rama) module, queried through a pullable EDN API, and visualized in a Replicant SPA. Built on a beta version of Rama, it proved the pipeline end to end and shaped the generic platform that came after it.

Testing in Clojure - Tools and Techniques

How I structure testing across Clojure projects: Rich Comment Tests for internal functions, `deftest` for system boundaries, Kaocha to run both, Malli validation at entry points only, embedded services for integration tests, and containerized services for load tests. All wrapped behind `bb test` and `bb rct` so nobody needs to remember runner flags.

Choosing a Git Workflow

What Git workflow is suitable for your project: trunk-based, feature branching, forking, release branching, release candidate workflow, Feature branching to develop, GitFlow

Date and Time in Clojure with Tick

Time in programming has too many representations, and jumping between them is where bugs live. This article walks the progression from `timestamp` to `instant` using [juxt/tick](https://github.com/juxt/tick), explains why an offset is not a zone, and shows the DST edge case where adding "one day" gives two different answers depending on whether you add a `duration` or a `period`.

Apex Domain to Subdomain Redirect

The apex domain problem: `flybot.sg` cannot 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.

Monte Carlo Tree Search for Card Games in Clojure

A draft implementation of a game-agnostic AI for Flybot's card games using Monte Carlo Tree Search. The implementation depends solely on a `Game` protocol from a shared library, so any game that implements the protocol gets MCTS for free. So far it has only been tested with two games (Big Two, PDK) and is not yet used in production. A colleague will be iterating on it next. Pure MCTS turned out to…

MAGIC Compiler and Nostrand Integration

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](https://github.com/nasser), the author of the [MAGIC](https://github.com/nasser/magic) compiler, to stabilize and optimize the toolchain. My main…

Card Game APIs in Clojure

A client runs more than a dozen card and mahjong games on a single Clojure `Game` protocol, wrapped by a `meta-game` engine that adds rounds, scoring, and tournaments. Because `meta-game` implements that same protocol, one game-agnostic server runs all of them, and because the libraries are `.cljc`, the same logic runs on the JVM backend and, through [MAGIC](https://github.com/flybot-sg/magic),…