Shopify
Online Store 2.0 themes, Liquid, sections, metafields and the Storefront API.
{% render 'card', product: product %} The Last Developer
After the AI apocalypse, I'm still here reading the code I ship. Shopify themes, Java backends and software that's thought through, optimized, functional and actually good to look at.
Sonic BlasterWarm-up145 BPM
Take control %Skills
Online Store 2.0 themes, Liquid, sections, metafields and the Storefront API.
{% render 'card', product: product %} Vanilla and Custom Elements, keeping the browser workload minimal.
customElements.define('x-tabs', Tabs) Typed React and Next.js interfaces, with contracts shared with the APIs.
type View = Partial<Summoner> Scroll-driven animations, :has(), container queries and @property instead of JavaScript.
animation-timeline: view() Records, streams and concurrency for queues, schedulers and services on Debian VPSes.
record Rank(String tier, int lp) {} REST controllers on embedded Tomcat, validation and scheduled jobs.
@GetMapping("/profile/{puuid}") Canonical data, aggregation pipelines and facets for statistics.
db.match.aggregate(pipeline) Relational schemas and hand-written queries. MariaDB in production for guilds and settings.
SELECT prefix FROM guild WHERE id = ? Projects
A Java backend and a Next.js frontend forming a single League of Legends statistics platform. Pick a scenario and see what happens behind each request.
Discord bot and League of Legends statistics engine, written in Java. The APIs never wait for Riot: they read from Redis and Mongo and queue the rest.
Example with indicative timings. Riot calls always go through the queue.
League of Legends statistics inside a virtual operating system: every profile is a folder, every page a window, every path a URL.
Every command resolves a VFS node; the data comes from the Beebot APIs.
Shopify
Theme, component and integration development for fashion and luxury brands.
Filters built with :has() and attribute selectors. Liquid precomputes variantMap and sold-out states, JS only handles resets.
For Kappa: JSON metafields, hard-stop gradient swatches and hidden radios.
For Montura: bulk updates of seasonal fields across variants.
OneTrust wired into Shopify’s Customer Privacy API.
How the game works: CSS only
Every obstacle has a column: left = x × cell. No canvas, no coordinates in JS.
One keyframe translates the course by one tile in a loop; the cube stays still on the X axis.
The jump keyframes land on the obstacle columns, with cubic-bezier easing for gravity.
A click sets a data attribute: particles, shockwave and restart are CSS.
[data-obstacle] {
left: calc(var(--x) * var(--cell));
}
[data-world] {
animation: world var(--period) linear infinite;
}
@keyframes hop {
22%, 41% { translate: 0 0 }
31% { translate: 0 calc(-2.2 * var(--cell)) }
}
[data-lab]:has(#lab-grid:checked) [data-x]::after {
content: "x " attr(data-x);
} Philosophy
Code deserves thought, optimization and a little taste. It has to work and be good to read. Even after the AI apocalypse.
It is now part of the job and makes it faster. Control stays human, though: every line has to be understood, verified and chosen.
Whoever writes the code answers for it. Every piece of logic has one owner and every decision has a reason.
Explicit names, clear responsibilities, nothing superfluous. Clean code costs less with every change.
Brevity only has value if it stays readable. Less code means fewer bugs and less to maintain.
naming/no-type-in-name JAVA The declaration already says int: repeating it in the name is noise. A local integer is count, not itemCounterInt.
int itemCounterInt = items.size();int count = items.size();
naming/explicit-unit JAVA A long can hold seconds, milliseconds or nanoseconds: here the name has to say which. Better still, a type that already knows.
long start = System.currentTimeMillis();long timeout = 30;long startTimeMillis = System.currentTimeMillis();Duration timeout = Duration.ofSeconds(30);
naming/no-abbreviations JS Code is written once and read a hundred times. Three saved letters are not worth a single doubt.
const usrCfg = getCfg(req);const btn = el.querySelector('.btn');const userConfig = getConfig(request);const button = element.querySelector('[data-button]');
comments/name-over-comment JS If a condition needs a comment, it deserves a named constant.
// check if the user is an adminif (user.role === 'admin' && user.active) {const isAdmin = user.role === 'admin' && user.active;if (isAdmin) {
flow/early-return JAVA Rule out the cases that do not matter first, then the main path stays flat.
if (player != null) {if (player.isRanked()) {return player.getRank();}}return Rank.UNRANKED;if (player == null || !player.isRanked()) return Rank.UNRANKED;return player.getRank();
size/readable-lines JS The short version only wins if it reads better than the long one.
let r = false;for (let i = 0; i < p.v.length; i++) {if (p.v[i].a) r = true;}return r;return product.variants.some((variant) => variant.available);
Developers first. Then the product. Then the clients.
Gaming
My League of Legends stats, served by the Beebot API, plus a few clips. More games coming soon.
Season 2026 · Support main
Summary of loaded matches
No games match these filters.
Contact