[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,…
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…
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…
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…
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.
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,…
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.
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…
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…
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.
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.
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](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.
[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](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 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…
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.
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.
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.
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.
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 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`.
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.
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…
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…
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),…