1<!DOCTYPE html><html lang="en" class="h-full antialiased"><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width, initial-scale=1"/><link rel="preload" as="image" href="/_next/static/media/favicon.30-pyszslje08.png"/><link rel="stylesheet" href="/_next/static/chunks/2vr3f1cmxi6ll.css" data-precedence="next"/><link rel="preload" as="script" fetchPriority="low" href="/_next/static/chunks/21qns1qrna__5.js"/>
1<script src="/_next/static/chunks/08-g455en5rkr.js" async=""></script>
1<script src="/_next/static/chunks/0z2fecevmt073.js" async=""></script>
1<script src="/_next/static/chunks/1l_jcrjjdo2lo.js" async=""></script>
1<script src="/_next/static/chunks/turbopack-3lgdgw1q7apyf.js" async=""></script>
1<script src="/_next/static/chunks/1mea94bxzf98z.js" async=""></script>
1<script src="/_next/static/chunks/2o6yuqk6ct-vf.js" async=""></script>
1<script src="/_next/static/chunks/3myhzjsh1prxr.js" async=""></script>
1<script src="/_next/static/chunks/2x0vibu3f-k-p.js" async=""></script>
1<title>Projects - James Porter</title><meta name="description" content="Projects from James Porter"/><link rel="icon" href="/icon.png?icon.30-pyszslje08.png" sizes="512x512" type="image/png"/>
1<script src="/_next/static/chunks/0cz1d0mv5g_q7.js" noModule=""></script>
1</head><body class="flex h-full bg-zinc-200 dark:bg-black"><div hidden=""><!--$--><!--/$--></div>
1<script>((a,b,c,d,e,f,g,h)=>{let i=document.documentElement,j=["light","dark"];function k(b){var c;(Array.isArray(a)?a:[a]).forEach(a=>{let c="class"===a,d=c&&f?e.map(a=>f[a]||a):e;c?(i.classList.remove(...d),i.classList.add(f&&f[b]?f[b]:b)):i.setAttribute(a,b)}),c=b,h&&j.includes(c)&&(i.style.colorScheme=c)}if(d)k(d);else try{let a=localStorage.getItem(b)||c,d=g&&"system"===a?window.matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light":a;k(d)}catch(a){}})("class","theme","system",null,["light","dark"],null,true,true)</script>
1<div class="flex w-full"><div class="fixed inset-0 flex justify-center sm:px-8"><div class="flex w-full max-w-7xl lg:px-8"><div class="w-full bg-white ring-1 ring-zinc-100 dark:bg-zinc-900 dark:ring-zinc-300/20"></div></div></div><div class="relative flex w-full flex-col"><header class="pointer-events-none relative z-50 flex flex-none flex-col" style="height:var(--header-height);margin-bottom:var(--header-mb)"><div class="top-0 z-10 h-16 pt-6" style="position:var(--header-position)"><div class="sm:px-8 top-[var(--header-top,theme(spacing.6))] w-full" style="position:var(--header-inner-position)"><div class="mx-auto w-full max-w-7xl lg:px-8"><div class="relative px-4 sm:px-8 lg:px-12"><div class="mx-auto max-w-2xl lg:max-w-5xl"><div class="relative flex gap-4"><div class="flex flex-1"><div class="h-10 w-10 rounded-full bg-white/90 p-0.5 shadow-lg shadow-zinc-800/5 ring-1 ring-zinc-900/5 backdrop-blur dark:bg-zinc-800/90 dark:ring-white/10"><a aria-label="Home" class="pointer-events-auto" href="/"><img alt="" width="512" height="512" decoding="async" data-nimg="1" class="rounded-full bg-zinc-100 object-cover dark:bg-zinc-800 h-9 w-9" style="color:transparent" src="/_next/static/media/favicon.30-pyszslje08.png"/></a></div></div><div class="flex flex-1 justify-end md:justify-center"><div class="pointer-events-auto md:hidden" data-headlessui-state=""><button class="group flex items-center rounded-full bg-white/90 px-4 py-2 text-sm font-medium text-zinc-800 shadow-lg shadow-zinc-800/5 ring-1 ring-zinc-900/5 backdrop-blur dark:bg-zinc-800/90 dark:text-zinc-200 dark:ring-white/10 dark:hover:ring-white/20" type="button" aria-expanded="false" data-headlessui-state="">Menu<svg viewBox="0 0 8 6" aria-hidden="true" class="ml-3 h-auto w-2 stroke-zinc-500 group-hover:stroke-zinc-700 dark:group-hover:stroke-zinc-400"><path d="M1.75 1.75 4 4.25l2.25-2.5" fill="none" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path></svg></button></div><span hidden="" style="position:fixed;top:1px;left:1px;width:1px;height:0;padding:0;margin:-1px;overflow:hidden;clip:rect(0, 0, 0, 0);white-space:nowrap;border-width:0;display:none"></span><nav class="pointer-events-auto hidden md:block"><ul class="flex items-center rounded-full bg-white/90 px-3 text-sm font-medium text-zinc-800 shadow-lg shadow-zinc-800/5 ring-1 ring-zinc-900/5 backdrop-blur dark:bg-zinc-800/90 dark:text-zinc-200 dark:ring-white/10"><li><a class="relative block px-3 py-2 transition hover:text-sky-500 dark:hover:text-sky-400" href="/about">About</a></li><li><a class="relative block px-3 py-2 transition hover:text-sky-500 dark:hover:text-sky-400" href="/blog">Writing</a></li><li><a class="relative block px-3 py-2 transition text-sky-500 dark:text-sky-400" href="/projects">Projects<span class="absolute inset-x-1 -bottom-px h-px bg-gradient-to-r from-sky-500/0 via-sky-500/40 to-sky-500/0 dark:from-sky-400/0 dark:via-sky-400/40 dark:to-sky-400/0"></span></a></li><li class="flex items-center"><span class="h-4 w-px bg-zinc-900/10 dark:bg-white/10" aria-hidden="true"></span><button type="button" aria-label="Search the site (Ctrl K)" title="Search (Ctrl K)" class="flex shrink-0 items-center gap-1.5 px-3 py-2 transition hover:text-sky-500 dark:hover:text-sky-400"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-search h-4 w-4 shrink-0" aria-hidden="true"><circle cx="11" cy="11" r="8"></circle><path d="m21 21-4.3-4.3"></path></svg><kbd class="hidden whitespace-nowrap rounded border border-zinc-900/10 px-1 py-px font-sans text-xs font-semibold leading-tight text-zinc-500 lg:inline-block dark:border-white/15 dark:text-zinc-400">Ctrl K</kbd></button></li></ul></nav></div><div class="flex justify-end gap-2 md:flex-1"><div class="pointer-events-auto md:hidden"><button type="button" aria-label="Search the site (Ctrl K)" title="Search (Ctrl K)" class="group flex h-full items-center rounded-full bg-white/90 px-3 py-2 text-zinc-500 shadow-lg shadow-zinc-800/5 ring-1 ring-zinc-900/5 backdrop-blur transition hover:text-sky-500 dark:bg-zinc-800/90 dark:text-zinc-400 dark:ring-white/10 dark:hover:text-sky-400 dark:hover:ring-white/20"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-search h-4 w-4 shrink-0" aria-hidden="true"><circle cx="11" cy="11" r="8"></circle><path d="m21 21-4.3-4.3"></path></svg><kbd class="hidden whitespace-nowrap rounded border border-zinc-900/10 px-1 py-px font-sans text-xs font-semibold leading-tight text-zinc-500 lg:inline-block dark:border-white/15 dark:text-zinc-400">Ctrl K</kbd></button></div><div class="pointer-events-auto"><button type="button" aria-label="Toggle theme" class="group rounded-full bg-white/90 px-3 py-2 shadow-lg shadow-zinc-800/5 ring-1 ring-zinc-900/5 backdrop-blur transition dark:bg-zinc-800/90 dark:ring-white/10 dark:hover:ring-white/20"><svg viewBox="0 0 24 24" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" class="h-6 w-6 fill-zinc-100 stroke-zinc-500 transition group-hover:fill-zinc-200 group-hover:stroke-zinc-700 dark:hidden [@media(prefers-color-scheme:dark)]:fill-sky-50 [@media(prefers-color-scheme:dark)]:stroke-sky-500 [@media(prefers-color-scheme:dark)]:group-hover:fill-sky-50 [@media(prefers-color-scheme:dark)]:group-hover:stroke-sky-600"><path d="M8 12.25A4.25 4.25 0 0 1 12.25 8v0a4.25 4.25 0 0 1 4.25 4.25v0a4.25 4.25 0 0 1-4.25 4.25v0A4.25 4.25 0 0 1 8 12.25v0Z"></path><path d="M12.25 3v1.5M21.5 12.25H20M18.791 18.791l-1.06-1.06M18.791 5.709l-1.06 1.06M12.25 20v1.5M4.5 12.25H3M6.77 6.77 5.709 5.709M6.77 17.73l-1.061 1.061" fill="none"></path></svg>
1<svg viewBox="0 0 24 24" aria-hidden="true" class="hidden h-6 w-6 fill-zinc-700 stroke-zinc-500 transition dark:block [@media(prefers-color-scheme:dark)]:group-hover:stroke-zinc-400 [@media_not_(prefers-color-scheme:dark)]:fill-sky-400/10 [@media_not_(prefers-color-scheme:dark)]:stroke-sky-500"><path d="M17.25 16.22a6.937 6.937 0 0 1-9.47-9.47 7.451 7.451 0 1 0 9.47 9.47ZM12.75 7C17 7 17 2.75 17 2.75S17 7 21.25 7C17 7 17 11.25 17 11.25S17 7 12.75 7Z" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path></svg></button></div></div></div></div></div></div></div></div></header><main class="flex-auto"><div class="sm:px-8 mt-16 sm:mt-32"><div class="mx-auto w-full max-w-7xl lg:px-8"><div class="relative px-4 sm:px-8 lg:px-12"><div class="mx-auto max-w-2xl lg:max-w-5xl"><header class="max-w-2xl"><h1 class="text-4xl font-bold tracking-tight text-zinc-800 sm:text-5xl dark:text-zinc-100">Projects</h1><p class="mt-6 text-base text-zinc-600 dark:text-zinc-400">Here are a few of the commercial apps, free apps and open source things I've built. Filter them by the platforms they run on and the areas they are in.</p></header><div class="mt-16 sm:mt-20"><div class="flex flex-col gap-12"><div class="flex flex-col gap-3 rounded-2xl border border-zinc-100 p-4 sm:p-6 dark:border-zinc-700/40"><div role="group" aria-label="Platform" class="flex flex-row flex-wrap items-center gap-2"><span class="w-20 shrink-0 text-sm font-semibold text-zinc-800 dark:text-zinc-100">Platform</span><button type="button" aria-pressed="false" class="rounded-md border px-2 py-0.5 text-xs font-semibold transition border-zinc-200 text-zinc-600 hover:border-zinc-300 hover:text-zinc-800 dark:border-zinc-700 dark:text-zinc-400 dark:hover:border-zinc-500 dark:hover:text-zinc-200">Web</button><button type="button" aria-pressed="false" class="rounded-md border px-2 py-0.5 text-xs font-semibold transition border-zinc-200 text-zinc-600 hover:border-zinc-300 hover:text-zinc-800 dark:border-zinc-700 dark:text-zinc-400 dark:hover:border-zinc-500 dark:hover:text-zinc-200">iOS</button><button type="button" aria-pressed="false" class="rounded-md border px-2 py-0.5 text-xs font-semibold transition border-zinc-200 text-zinc-600 hover:border-zinc-300 hover:text-zinc-800 dark:border-zinc-700 dark:text-zinc-400 dark:hover:border-zinc-500 dark:hover:text-zinc-200">MacOS</button><button type="button" aria-pressed="false" class="rounded-md border px-2 py-0.5 text-xs font-semibold transition border-zinc-200 text-zinc-600 hover:border-zinc-300 hover:text-zinc-800 dark:border-zinc-700 dark:text-zinc-400 dark:hover:border-zinc-500 dark:hover:text-zinc-200">Android</button></div><div role="group" aria-label="Area" class="flex flex-row flex-wrap items-center gap-2"><span class="w-20 shrink-0 text-sm font-semibold text-zinc-800 dark:text-zinc-100">Area</span><button type="button" aria-pressed="false" class="rounded-md border px-2 py-0.5 text-xs font-semibold transition border-zinc-200 text-zinc-600 hover:border-zinc-300 hover:text-zinc-800 dark:border-zinc-700 dark:text-zinc-400 dark:hover:border-zinc-500 dark:hover:text-zinc-200">Creative Coding</button><button type="button" aria-pressed="false" class="rounded-md border px-2 py-0.5 text-xs font-semibold transition border-zinc-200 text-zinc-600 hover:border-zinc-300 hover:text-zinc-800 dark:border-zinc-700 dark:text-zinc-400 dark:hover:border-zinc-500 dark:hover:text-zinc-200">Apps</button><button type="button" aria-pressed="false" class="rounded-md border px-2 py-0.5 text-xs font-semibold transition border-zinc-200 text-zinc-600 hover:border-zinc-300 hover:text-zinc-800 dark:border-zinc-700 dark:text-zinc-400 dark:hover:border-zinc-500 dark:hover:text-zinc-200">Learning</button><button type="button" aria-pressed="false" class="rounded-md border px-2 py-0.5 text-xs font-semibold transition border-zinc-200 text-zinc-600 hover:border-zinc-300 hover:text-zinc-800 dark:border-zinc-700 dark:text-zinc-400 dark:hover:border-zinc-500 dark:hover:text-zinc-200">Programming</button><button type="button" aria-pressed="false" class="rounded-md border px-2 py-0.5 text-xs font-semibold transition border-zinc-200 text-zinc-600 hover:border-zinc-300 hover:text-zinc-800 dark:border-zinc-700 dark:text-zinc-400 dark:hover:border-zinc-500 dark:hover:text-zinc-200">Library</button></div><div class="flex flex-row flex-wrap items-center gap-3 text-sm text-zinc-600 dark:text-zinc-400"><span>All 30 projects</span></div></div><ul role="list" class="grid grid-cols-1 gap-x-12 gap-y-16 sm:grid-cols-2 lg:grid-cols-3"><li id="scenic-prism" class="flex scroll-mt-28 flex-col gap-2"><h3 class="text-base font-semibold tracking-tight text-zinc-800 dark:text-zinc-100">Scenic Prism</h3><p class="-mt-2 text-sm text-zinc-600 dark:text-zinc-400">Started <!-- -->2026</p><p>A version of Scenic Forge which supports dispersion for colourful prism-like splitting of light. Can choose from RGB, rainbow or non-physically inspired approaches.</p><a href="https://scenic-prism.pages.dev/" target="_blank" rel="noopener noreferrer" class="inline-block"><div class="mr-2 flex flex-row items-center gap-2 font-semibold text-sky-600 hover:text-sky-400"><svg viewBox="0 0 24 24" aria-hidden="true" class="h-4 w-4"><path d="M15.712 11.823a.75.75 0 1 0 1.06 1.06l-1.06-1.06Zm-4.95 1.768a.75.75 0 0 0 1.06-1.06l-1.
106 1.06Zm-2.475-1.414a.75.75 0 1 0-1.06-1.06l1.06 1.06Zm4.95-1.768a.75.75 0 1 0-1.06 1.06l1.06-1.06Zm3.359.53-.884.884 1.06 1.06.885-.883-1.061-1.06Zm-4.95-2.12 1.414-1.415L12 6.344l-1.415 1.413 1.061 1.061Zm0 3.535a2.5 2.5 0 0 1 0-3.536l-1.06-1.06a4 4 0 0 0 0 5.656l1.06-1.06Zm4.95-4.95a2.5 2.5 0 0 1 0 3.535L17.656 12a4 4 0 0 0 0-5.657l-1.06 1.06Zm1.06-1.06a4 4 0 0 0-5.656 0l1.06 1.06a2.5 2.5 0 0 1 3.536 0l1.06-1.06Zm-7.07 7.07.176.177 1.06-1.06-.176-.177-1.06 1.06Zm-3.183-.353.884-.884-1.06-1.06-.884.883 1.06 1.06Zm4.95 2.121-1.414 1.414 1.06 1.06 1.415-1.413-1.06-1.061Zm0-3.536a2.5 2.5 0 0 1 0 3.536l1.06 1.06a4 4 0 0 0 0-5.656l-1.06 1.06Zm-4.95 4.95a2.5 2.5 0 0 1 0-3.535L6.344 12a4 4 0 0 0 0 5.656l1.06-1.06Zm-1.06 1.06a4 4 0 0 0 5.657 0l-1.061-1.06a2.5 2.5 0 0 1-3.535 0l-1.061 1.06Zm7.07-7.07-.176-.177-1.06 1.06.176.178 1.06-1.061Z" fill="currentColor"></path></svg>Scenic Prism</div></a><div class="mt-auto flex flex-col gap-1 pt-2"><div class="flex flex-row flex-wrap gap-1"><span class="border px-2 py-0.5 text-xs font-semibold rounded-l-md bg-rose-100 border-rose-200 text-rose-800 dark:bg-rose-900 dark:border-rose-700 dark:text-rose-100">Creative Coding</span><span class="border px-2 py-0.5 text-xs font-semibold bg-teal-100 border-teal-200 text-teal-800 dark:bg-teal-900 dark:border-teal-700 dark:text-teal-100">Programming</span><span class="border px-2 py-0.5 text-xs font-semibold rounded-r-md bg-orange-100 border-orange-200 text-orange-800 dark:bg-orange-900 dark:border-orange-700 dark:text-orange-100">Library</span></div><div class="flex flex-row flex-wrap gap-1"><span class="border px-2 py-0.5 text-xs font-semibold rounded-md bg-sky-100 border-sky-200 text-sky-800 dark:bg-sky-900 dark:border-sky-700 dark:text-sky-100">Web</span></div></div></li><li id="acrylic-blend" class="flex scroll-mt-28 flex-col gap-2"><h3 class="text-base font-semibold tracking-tight text-zinc-800 dark:text-zinc-100">Acrylic Blend</h3><p class="-mt-2 text-sm text-zinc-600 dark:text-zinc-400">Started <!-- -->2026</p><p>A WebGPU powered painting library, along with a demo painting/canvas app built on it.</p><a href="https://acrylic-blend.pages.dev/" target="_blank" rel="noopener noreferrer" class="inline-block"><div class="mr-2 flex flex-row items-center gap-2 font-semibold text-sky-600 hover:text-sky-400"><svg viewBox="0 0 24 24" aria-hidden="true" class="h-4 w-4"><path d="M15.712 11.823a.75.75 0 1 0 1.06 1.06l-1.06-1.06Zm-4.95 1.768a.75.75 0 0 0 1.06-1.06l-1.06 1.06Zm-2.475-1.414a.75.75 0 1 0-1.06-1.06l1.06 1.06Zm4.95-1.768a.75.75 0 1 0-1.06 1.06l1.06-1.06Zm3.359.53-.884.884 1.06 1.06.885-.883-1.061-1.06Zm-4.95-2.12 1.414-1.415L12 6.344l-1.415 1.413 1.061 1.061Zm0 3.535a2.5 2.5 0 0 1 0-3.536l-1.06-1.06a4 4 0 0 0 0 5.656l1.06-1.06Zm4.95-4.95a2.5 2.5 0 0 1 0 3.535L17.656 12a4 4 0 0 0 0-5.657l-1.06 1.06Zm1.06-1.06a4 4 0 0 0-5.656 0l1.06 1.06a2.5 2.5 0 0 1 3.536 0l1.06-1.06Zm-7.07 7.07.176.177 1.06-1.06-.176-.177-1.06 1.06Zm-3.183-.353.884-.884-1.06-1.06-.884.883 1.06 1.06Zm4.95 2.121-1.414 1.414 1.06 1.06 1.415-1.413-1.06-1.061Zm0-3.536a2.5 2.5 0 0 1 0 3.536l1.06 1.06a4 4 0 0 0 0-5.656l-1.06 1.06Zm-4.95 4.95a2.5 2.5 0 0 1 0-3.535L6.344 12a4 4 0 0 0 0 5.656l1.06-1.06Zm-1.06 1.06a4 4 0 0 0 5.657 0l-1.061-1.06a2.5 2.5 0 0 1-3.535 0l-1.061 1.06Zm7.07-7.07-.176-.177-1.06 1.06.176.178 1.06-1.061Z" fill="currentColor"></path></svg>Acrylic Blend</div></a><div class="mt-auto flex flex-col gap-1 pt-2"><div class="flex flex-row flex-wrap gap-1"><span class="border px-2 py-0.5 text-xs font-semibold rounded-l-md bg-rose-100 border-rose-200 text-rose-800 dark:bg-rose-900 dark:border-rose-700 dark:text-rose-100">Creative Coding</span><span class="border px-2 py-0.5 text-xs font-semibold bg-amber-100 border-amber-200 text-amber-800 dark:bg-amber-900 dark:border-amber-700 dark:text-amber-100">Apps</span><span class="border px-2 py-0.5 text-xs font-semibold rounded-r-md bg-orange-100 border-orange-200 text-orange-800 dark:bg-orange-900 dark:border-orange-700 dark:text-orange-100">Library</span></div><div class="flex flex-row flex-wrap gap-1"><span class="border px-2 py-0.5 text-xs font-semibold rounded-md bg-sky-100 border-sky-200 text-sky-800 dark:bg-sky-900 dark:border-sky-700 dark:text-sky-100">Web</span></div></div></li><li id="scenic-forge" class="flex scroll-mt-28 flex-col gap-2"><h3 class="text-base font-semibold tracking-tight text-zinc-800 dark:text-zinc-100">Scenic Forge</h3><p class="-mt-2 text-sm text-zinc-600 dark:text-zinc-400">Started <!-- -->2026</p><p>A WebGPU version of Scenic Draft, with compatible scenes but more performant rendering.</p><a href="https://scenic-forge.pages.dev/" target="_blank" rel="noopener noreferrer" class="inline-block"><div class="mr-2 flex flex-row items-center gap-2 font-semibold text-sky-600 hover:text-sky-400"><svg viewBox="0 0 24 24" aria-hidden="true" class="h-4 w-4"><path d="M15.712 11.823a.75.75 0 1 0 1.06 1.06l-1.06-1.06Zm-4.95 1.768a.75.75 0 0 0 1.06-1.06l-1.
106 1.06Zm-2.475-1.414a.75.75 0 1 0-1.06-1.06l1.06 1.06Zm4.95-1.768a.75.75 0 1 0-1.06 1.06l1.06-1.06Zm3.359.53-.884.884 1.06 1.06.885-.883-1.061-1.06Zm-4.95-2.12 1.414-1.415L12 6.344l-1.415 1.413 1.061 1.061Zm0 3.535a2.5 2.5 0 0 1 0-3.536l-1.06-1.06a4 4 0 0 0 0 5.656l1.06-1.06Zm4.95-4.95a2.5 2.5 0 0 1 0 3.535L17.656 12a4 4 0 0 0 0-5.657l-1.06 1.06Zm1.06-1.06a4 4 0 0 0-5.656 0l1.06 1.06a2.5 2.5 0 0 1 3.536 0l1.06-1.06Zm-7.07 7.07.176.177 1.06-1.06-.176-.177-1.06 1.06Zm-3.183-.353.884-.884-1.06-1.06-.884.883 1.06 1.06Zm4.95 2.121-1.414 1.414 1.06 1.06 1.415-1.413-1.06-1.061Zm0-3.536a2.5 2.5 0 0 1 0 3.536l1.06 1.06a4 4 0 0 0 0-5.656l-1.06 1.06Zm-4.95 4.95a2.5 2.5 0 0 1 0-3.535L6.344 12a4 4 0 0 0 0 5.656l1.06-1.06Zm-1.06 1.06a4 4 0 0 0 5.657 0l-1.061-1.06a2.5 2.5 0 0 1-3.535 0l-1.061 1.06Zm7.07-7.07-.176-.177-1.06 1.06.176.178 1.06-1.061Z" fill="currentColor"></path></svg>Scenic Forge</div></a><div class="mt-auto flex flex-col gap-1 pt-2"><div class="flex flex-row flex-wrap gap-1"><span class="border px-2 py-0.5 text-xs font-semibold rounded-l-md bg-rose-100 border-rose-200 text-rose-800 dark:bg-rose-900 dark:border-rose-700 dark:text-rose-100">Creative Coding</span><span class="border px-2 py-0.5 text-xs font-semibold bg-teal-100 border-teal-200 text-teal-800 dark:bg-teal-900 dark:border-teal-700 dark:text-teal-100">Programming</span><span class="border px-2 py-0.5 text-xs font-semibold rounded-r-md bg-orange-100 border-orange-200 text-orange-800 dark:bg-orange-900 dark:border-orange-700 dark:text-orange-100">Library</span></div><div class="flex flex-row flex-wrap gap-1"><span class="border px-2 py-0.5 text-xs font-semibold rounded-md bg-sky-100 border-sky-200 text-sky-800 dark:bg-sky-900 dark:border-sky-700 dark:text-sky-100">Web</span></div></div></li><li id="isometrically" class="flex scroll-mt-28 flex-col gap-2"><h3 class="text-base font-semibold tracking-tight text-zinc-800 dark:text-zinc-100">Isometrically</h3><p class="-mt-2 text-sm text-zinc-600 dark:text-zinc-400">Started <!-- -->2026</p><p>I had an iOS App that allowed for isometric (triangle grid) based drawings. I recently rebuilt a much more powerful version for the web, with easy-to-drop-in shapes and 'sunlight angle' control. Along with many standard features from vector graphics editors such as text (but specially set up for isometric context). It also has a powerful undo/redo/history system and export to common formats.</p><a href="https://isometrically.pages.dev/" target="_blank" rel="noopener noreferrer" class="inline-block"><div class="mr-2 flex flex-row items-center gap-2 font-semibold text-sky-600 hover:text-sky-400"><svg viewBox="0 0 24 24" aria-hidden="true" class="h-4 w-4"><path d="M15.712 11.823a.75.75 0 1 0 1.06 1.06l-1.06-1.06Zm-4.95 1.768a.75.75 0 0 0 1.06-1.06l-1.06 1.06Zm-2.475-1.414a.75.75 0 1 0-1.06-1.06l1.06 1.06Zm4.95-1.768a.75.75 0 1 0-1.06 1.06l1.06-1.06Zm3.359.53-.884.884 1.06 1.06.885-.883-1.061-1.06Zm-4.95-2.12 1.414-1.415L12 6.344l-1.415 1.413 1.061 1.061Zm0 3.535a2.5 2.5 0 0 1 0-3.536l-1.06-1.06a4 4 0 0 0 0 5.656l1.06-1.06Zm4.95-4.95a2.5 2.5 0 0 1 0 3.535L17.656 12a4 4 0 0 0 0-5.657l-1.06 1.06Zm1.06-1.06a4 4 0 0 0-5.656 0l1.06 1.06a2.5 2.5 0 0 1 3.536 0l1.06-1.06Zm-7.07 7.07.176.177 1.06-1.06-.176-.177-1.06 1.06Zm-3.183-.353.884-.884-1.06-1.06-.884.883 1.06 1.06Zm4.95 2.121-1.414 1.414 1.06 1.06 1.415-1.413-1.06-1.061Zm0-3.536a2.5 2.5 0 0 1 0 3.536l1.06 1.06a4 4 0 0 0 0-5.656l-1.06 1.06Zm-4.95 4.95a2.5 2.5 0 0 1 0-3.535L6.344 12a4 4 0 0 0 0 5.656l1.06-1.06Zm-1.06 1.06a4 4 0 0 0 5.657 0l-1.061-1.06a2.5 2.5 0 0 1-3.535 0l-1.061 1.06Zm7.07-7.07-.176-.177-1.06 1.06.176.178 1.06-1.061Z" fill="currentColor"></path></svg>Isometrically</div></a><div class="mt-auto flex flex-col gap-1 pt-2"><div class="flex flex-row flex-wrap gap-1"><span class="border px-2 py-0.5 text-xs font-semibold rounded-l-md bg-rose-100 border-rose-200 text-rose-800 dark:bg-rose-900 dark:border-rose-700 dark:text-rose-100">Creative Coding</span><span class="border px-2 py-0.5 text-xs font-semibold rounded-r-md bg-amber-100 border-amber-200 text-amber-800 dark:bg-amber-900 dark:border-amber-700 dark:text-amber-100">Apps</span></div><div class="flex flex-row flex-wrap gap-1"><span class="border px-2 py-0.5 text-xs font-semibold rounded-md bg-sky-100 border-sky-200 text-sky-800 dark:bg-sky-900 dark:border-sky-700 dark:text-sky-100">Web</span></div></div></li><li id="swiftui-glossary" class="flex scroll-mt-28 flex-col gap-2"><h3 class="text-base font-semibold tracking-tight text-zinc-800 dark:text-zinc-100">SwiftUI Glossary</h3><p class="-mt-2 text-sm text-zinc-600 dark:text-zinc-400">Started <!-- -->2026</p><p>A guide to what SwiftUI does and what Apple calls it. With flashcards to test your knowledge.</p><a href="https://swiftui-glossary.pages.dev/" target="_blank" rel="noopener noreferrer" class="inline-block"><div class="mr-2 flex flex-row items-center gap-2 font-semibold text-sky-600 hover:text-sky-400"><svg viewBox="0 0 24 24" aria-hidden="true" class="h-4 w-4"><path d="M15.712 11.823a.75.75 0 1 0 1.06 1.06l-1.06-1.06Zm-4.95 1.768a.75.75 0 0 0 1.06-1.06l-1.
106 1.06Zm-2.475-1.414a.75.75 0 1 0-1.06-1.06l1.06 1.06Zm4.95-1.768a.75.75 0 1 0-1.06 1.06l1.06-1.06Zm3.359.53-.884.884 1.06 1.06.885-.883-1.061-1.06Zm-4.95-2.12 1.414-1.415L12 6.344l-1.415 1.413 1.061 1.061Zm0 3.535a2.5 2.5 0 0 1 0-3.536l-1.06-1.06a4 4 0 0 0 0 5.656l1.06-1.06Zm4.95-4.95a2.5 2.5 0 0 1 0 3.535L17.656 12a4 4 0 0 0 0-5.657l-1.06 1.06Zm1.06-1.06a4 4 0 0 0-5.656 0l1.06 1.06a2.5 2.5 0 0 1 3.536 0l1.06-1.06Zm-7.07 7.07.176.177 1.06-1.06-.176-.177-1.06 1.06Zm-3.183-.353.884-.884-1.06-1.06-.884.883 1.06 1.06Zm4.95 2.121-1.414 1.414 1.06 1.06 1.415-1.413-1.06-1.061Zm0-3.536a2.5 2.5 0 0 1 0 3.536l1.06 1.06a4 4 0 0 0 0-5.656l-1.06 1.06Zm-4.95 4.95a2.5 2.5 0 0 1 0-3.535L6.344 12a4 4 0 0 0 0 5.656l1.06-1.06Zm-1.06 1.06a4 4 0 0 0 5.657 0l-1.061-1.06a2.5 2.5 0 0 1-3.535 0l-1.061 1.06Zm7.07-7.07-.176-.177-1.06 1.06.176.178 1.06-1.061Z" fill="currentColor"></path></svg>SwiftUI Glossary</div></a><div class="mt-auto flex flex-col gap-1 pt-2"><div class="flex flex-row flex-wrap gap-1"><span class="border px-2 py-0.5 text-xs font-semibold rounded-l-md bg-violet-100 border-violet-200 text-violet-800 dark:bg-violet-900 dark:border-violet-700 dark:text-violet-100">Learning</span><span class="border px-2 py-0.5 text-xs font-semibold rounded-r-md bg-teal-100 border-teal-200 text-teal-800 dark:bg-teal-900 dark:border-teal-700 dark:text-teal-100">Programming</span></div><div class="flex flex-row flex-wrap gap-1"><span class="border px-2 py-0.5 text-xs font-semibold rounded-md bg-sky-100 border-sky-200 text-sky-800 dark:bg-sky-900 dark:border-sky-700 dark:text-sky-100">Web</span></div></div></li><li id="learn-lean-4" class="flex scroll-mt-28 flex-col gap-2"><h3 class="text-base font-semibold tracking-tight text-zinc-800 dark:text-zinc-100">Learn Lean 4</h3><p class="-mt-2 text-sm text-zinc-600 dark:text-zinc-400">Started <!-- -->2026</p><p>A complete-ish course in both learning how to do proofs with Lean 4 and learning how to use it as a programming language. Around 200 individual exercises (and counting!) with annotated solutions. No installs required.</p><a href="https://learn-lean.pages.dev/" target="_blank" rel="noopener noreferrer" class="inline-block"><div class="mr-2 flex flex-row items-center gap-2 font-semibold text-sky-600 hover:text-sky-400"><svg viewBox="0 0 24 24" aria-hidden="true" class="h-4 w-4"><path d="M15.712 11.823a.75.75 0 1 0 1.06 1.06l-1.06-1.06Zm-4.95 1.768a.75.75 0 0 0 1.06-1.06l-1.06 1.06Zm-2.475-1.414a.75.75 0 1 0-1.06-1.06l1.06 1.06Zm4.95-1.768a.75.75 0 1 0-1.06 1.06l1.06-1.06Zm3.359.53-.884.884 1.06 1.06.885-.883-1.061-1.06Zm-4.95-2.12 1.414-1.415L12 6.344l-1.415 1.413 1.061 1.061Zm0 3.535a2.5 2.5 0 0 1 0-3.536l-1.06-1.06a4 4 0 0 0 0 5.656l1.06-1.06Zm4.95-4.95a2.5 2.5 0 0 1 0 3.535L17.656 12a4 4 0 0 0 0-5.657l-1.06 1.06Zm1.06-1.06a4 4 0 0 0-5.656 0l1.06 1.06a2.5 2.5 0 0 1 3.536 0l1.06-1.06Zm-7.07 7.07.176.177 1.06-1.06-.176-.177-1.06 1.06Zm-3.183-.353.884-.884-1.06-1.06-.884.883 1.06 1.06Zm4.95 2.121-1.414 1.414 1.06 1.06 1.415-1.413-1.06-1.061Zm0-3.536a2.5 2.5 0 0 1 0 3.536l1.06 1.06a4 4 0 0 0 0-5.656l-1.06 1.06Zm-4.95 4.95a2.5 2.5 0 0 1 0-3.535L6.344 12a4 4 0 0 0 0 5.656l1.06-1.06Zm-1.06 1.06a4 4 0 0 0 5.657 0l-1.061-1.06a2.5 2.5 0 0 1-3.535 0l-1.061 1.06Zm7.07-7.07-.176-.177-1.06 1.06.176.178 1.06-1.061Z" fill="currentColor"></path></svg>Learn Lean 4</div></a><div class="mt-auto flex flex-col gap-1 pt-2"><div class="flex flex-row flex-wrap gap-1"><span class="border px-2 py-0.5 text-xs font-semibold rounded-l-md bg-violet-100 border-violet-200 text-violet-800 dark:bg-violet-900 dark:border-violet-700 dark:text-violet-100">Learning</span><span class="border px-2 py-0.5 text-xs font-semibold rounded-r-md bg-teal-100 border-teal-200 text-teal-800 dark:bg-teal-900 dark:border-teal-700 dark:text-teal-100">Programming</span></div><div class="flex flex-row flex-wrap gap-1"><span class="border px-2 py-0.5 text-xs font-semibold rounded-md bg-sky-100 border-sky-200 text-sky-800 dark:bg-sky-900 dark:border-sky-700 dark:text-sky-100">Web</span></div></div></li><li id="the-book-of-tsl" class="flex scroll-mt-28 flex-col gap-2"><h3 class="text-base font-semibold tracking-tight text-zinc-800 dark:text-zinc-100">The Book of TSL</h3><p class="-mt-2 text-sm text-zinc-600 dark:text-zinc-400">Started <!-- -->2026</p><p>Around 200 concise examples showing how to get stuff done with Three.js Shading Language. Covering fragment and vertex shaders, raymarching SDFs, lighting and much more.</p><a href="https://the-book-of-tsl.pages.dev/" target="_blank" rel="noopener noreferrer" class="inline-block"><div class="mr-2 flex flex-row items-center gap-2 font-semibold text-sky-600 hover:text-sky-400"><svg viewBox="0 0 24 24" aria-hidden="true" class="h-4 w-4"><path d="M15.712 11.823a.75.75 0 1 0 1.06 1.06l-1.06-1.06Zm-4.95 1.768a.75.75 0 0 0 1.06-1.06l-1.
106 1.06Zm-2.475-1.414a.75.75 0 1 0-1.06-1.06l1.06 1.06Zm4.95-1.768a.75.75 0 1 0-1.06 1.06l1.06-1.06Zm3.359.53-.884.884 1.06 1.06.885-.883-1.061-1.06Zm-4.95-2.12 1.414-1.415L12 6.344l-1.415 1.413 1.061 1.061Zm0 3.535a2.5 2.5 0 0 1 0-3.536l-1.06-1.06a4 4 0 0 0 0 5.656l1.06-1.06Zm4.95-4.95a2.5 2.5 0 0 1 0 3.535L17.656 12a4 4 0 0 0 0-5.657l-1.06 1.06Zm1.06-1.06a4 4 0 0 0-5.656 0l1.06 1.06a2.5 2.5 0 0 1 3.536 0l1.06-1.06Zm-7.07 7.07.176.177 1.06-1.06-.176-.177-1.06 1.06Zm-3.183-.353.884-.884-1.06-1.06-.884.883 1.06 1.06Zm4.95 2.121-1.414 1.414 1.06 1.06 1.415-1.413-1.06-1.061Zm0-3.536a2.5 2.5 0 0 1 0 3.536l1.06 1.06a4 4 0 0 0 0-5.656l-1.06 1.06Zm-4.95 4.95a2.5 2.5 0 0 1 0-3.535L6.344 12a4 4 0 0 0 0 5.656l1.06-1.06Zm-1.06 1.06a4 4 0 0 0 5.657 0l-1.061-1.06a2.5 2.5 0 0 1-3.535 0l-1.061 1.06Zm7.07-7.07-.176-.177-1.06 1.06.176.178 1.06-1.061Z" fill="currentColor"></path></svg>The Book of TSL</div></a><div class="mt-auto flex flex-col gap-1 pt-2"><div class="flex flex-row flex-wrap gap-1"><span class="border px-2 py-0.5 text-xs font-semibold rounded-l-md bg-rose-100 border-rose-200 text-rose-800 dark:bg-rose-900 dark:border-rose-700 dark:text-rose-100">Creative Coding</span><span class="border px-2 py-0.5 text-xs font-semibold bg-violet-100 border-violet-200 text-violet-800 dark:bg-violet-900 dark:border-violet-700 dark:text-violet-100">Learning</span><span class="border px-2 py-0.5 text-xs font-semibold rounded-r-md bg-teal-100 border-teal-200 text-teal-800 dark:bg-teal-900 dark:border-teal-700 dark:text-teal-100">Programming</span></div><div class="flex flex-row flex-wrap gap-1"><span class="border px-2 py-0.5 text-xs font-semibold rounded-md bg-sky-100 border-sky-200 text-sky-800 dark:bg-sky-900 dark:border-sky-700 dark:text-sky-100">Web</span></div></div></li><li id="scenic-draft" class="flex scroll-mt-28 flex-col gap-2"><h3 class="text-base font-semibold tracking-tight text-zinc-800 dark:text-zinc-100">Scenic Draft</h3><p class="-mt-2 text-sm text-zinc-600 dark:text-zinc-400">Started <!-- -->2026</p><p>A minimalist raymarching, SDF WebGL2 rendering library. Renders beautiful photographic style images from simple specifications.</p><a href="https://scenic-draft.pages.dev" target="_blank" rel="noopener noreferrer" class="inline-block"><div class="mr-2 flex flex-row items-center gap-2 font-semibold text-sky-600 hover:text-sky-400"><svg viewBox="0 0 24 24" aria-hidden="true" class="h-4 w-4"><path d="M15.712 11.823a.75.75 0 1 0 1.06 1.06l-1.06-1.06Zm-4.95 1.768a.75.75 0 0 0 1.06-1.06l-1.06 1.06Zm-2.475-1.414a.75.75 0 1 0-1.06-1.06l1.06 1.06Zm4.95-1.768a.75.75 0 1 0-1.06 1.06l1.06-1.06Zm3.359.53-.884.884 1.06 1.06.885-.883-1.061-1.06Zm-4.95-2.12 1.414-1.415L12 6.344l-1.415 1.413 1.061 1.061Zm0 3.535a2.5 2.5 0 0 1 0-3.536l-1.06-1.06a4 4 0 0 0 0 5.656l1.06-1.06Zm4.95-4.95a2.5 2.5 0 0 1 0 3.535L17.656 12a4 4 0 0 0 0-5.657l-1.06 1.06Zm1.06-1.06a4 4 0 0 0-5.656 0l1.06 1.06a2.5 2.5 0 0 1 3.536 0l1.06-1.06Zm-7.07 7.07.176.177 1.06-1.06-.176-.177-1.06 1.06Zm-3.183-.353.884-.884-1.06-1.06-.884.883 1.06 1.06Zm4.95 2.121-1.414 1.414 1.06 1.06 1.415-1.413-1.06-1.061Zm0-3.536a2.5 2.5 0 0 1 0 3.536l1.06 1.06a4 4 0 0 0 0-5.656l-1.06 1.06Zm-4.95 4.95a2.5 2.5 0 0 1 0-3.535L6.344 12a4 4 0 0 0 0 5.656l1.06-1.06Zm-1.06 1.06a4 4 0 0 0 5.657 0l-1.061-1.06a2.5 2.5 0 0 1-3.535 0l-1.061 1.06Zm7.07-7.07-.176-.177-1.06 1.06.176.178 1.06-1.061Z" fill="currentColor"></path></svg>Scenic Draft (docs)</div></a><a href="https://www.npmjs.com/package/scenic-draft" target="_blank" rel="noopener noreferrer" class="inline-block"><div class="mr-2 flex flex-row items-center gap-2 font-semibold text-sky-600 hover:text-sky-400"><svg viewBox="0 0 24 24" aria-hidden="true" class="h-4 w-4"><path d="M15.712 11.823a.75.75 0 1 0 1.06 1.06l-1.06-1.06Zm-4.95 1.768a.75.75 0 0 0 1.06-1.06l-1.06 1.06Zm-2.475-1.414a.75.75 0 1 0-1.06-1.06l1.06 1.06Zm4.95-1.768a.75.75 0 1 0-1.06 1.06l1.06-1.06Zm3.359.53-.884.884 1.06 1.06.885-.883-1.061-1.06Zm-4.95-2.12 1.414-1.415L12 6.344l-1.415 1.413 1.061 1.061Zm0 3.535a2.5 2.5 0 0 1 0-3.536l-1.06-1.06a4 4 0 0 0 0 5.656l1.06-1.06Zm4.95-4.95a2.5 2.5 0 0 1 0 3.535L17.656 12a4 4 0 0 0 0-5.657l-1.06 1.06Zm1.06-1.06a4 4 0 0 0-5.656 0l1.06 1.06a2.5 2.5 0 0 1 3.536 0l1.06-1.06Zm-7.07 7.07.176.177 1.06-1.06-.176-.177-1.06 1.06Zm-3.183-.353.884-.884-1.06-1.06-.884.883 1.06 1.06Zm4.95 2.121-1.414 1.414 1.06 1.06 1.415-1.413-1.06-1.061Zm0-3.536a2.5 2.5 0 0 1 0 3.536l1.06 1.06a4 4 0 0 0 0-5.656l-1.06 1.06Zm-4.95 4.95a2.5 2.5 0 0 1 0-3.535L6.344 12a4 4 0 0 0 0 5.656l1.06-1.06Zm-1.06 1.06a4 4 0 0 0 5.657 0l-1.061-1.06a2.5 2.5 0 0 1-3.535 0l-1.061 1.06Zm7.07-7.07-.176-.177-1.06 1.06.176.178 1.06-1.061Z" fill="currentColor"></path></svg>Scenic Draft (npm)</div></a><div class="mt-auto flex flex-col gap-1 pt-2"><div class="flex flex-row flex-wrap gap-1"><span class="border px-2 py-0.5 text-xs font-semibold rounded-l-md bg-rose-100 border-rose-200 text-rose-800 dark:bg-rose-900 dark:border-rose-700 dark:text-rose-100">
1Creative Coding</span><span class="border px-2 py-0.5 text-xs font-semibold bg-teal-100 border-teal-200 text-teal-800 dark:bg-teal-900 dark:border-teal-700 dark:text-teal-100">Programming</span><span class="border px-2 py-0.5 text-xs font-semibold rounded-r-md bg-orange-100 border-orange-200 text-orange-800 dark:bg-orange-900 dark:border-orange-700 dark:text-orange-100">Library</span></div><div class="flex flex-row flex-wrap gap-1"><span class="border px-2 py-0.5 text-xs font-semibold rounded-md bg-sky-100 border-sky-200 text-sky-800 dark:bg-sky-900 dark:border-sky-700 dark:text-sky-100">Web</span></div></div></li><li id="code-sculpture-next-gen" class="flex scroll-mt-28 flex-col gap-2"><h3 class="text-base font-semibold tracking-tight text-zinc-800 dark:text-zinc-100">Code Sculpture (Next Gen)</h3><p class="-mt-2 text-sm text-zinc-600 dark:text-zinc-400">Started <!-- -->2026</p><p>I had an iOS App for years that allowed you to create 3D sculptures from simple rules. This is a completely rebuilt version for the web with all sorts of advanced features like video export and share by URL.</p><a href="https://code-sculpture.pages.dev/" target="_blank" rel="noopener noreferrer" class="inline-block"><div class="mr-2 flex flex-row items-center gap-2 font-semibold text-sky-600 hover:text-sky-400"><svg viewBox="0 0 24 24" aria-hidden="true" class="h-4 w-4"><path d="M15.712 11.823a.75.75 0 1 0 1.06 1.06l-1.06-1.06Zm-4.95 1.768a.75.75 0 0 0 1.06-1.06l-1.06 1.06Zm-2.475-1.414a.75.75 0 1 0-1.06-1.06l1.06 1.06Zm4.95-1.768a.75.75 0 1 0-1.06 1.06l1.06-1.06Zm3.359.53-.884.884 1.06 1.06.885-.883-1.061-1.06Zm-4.95-2.12 1.414-1.415L12 6.344l-1.415 1.413 1.061 1.061Zm0 3.535a2.5 2.5 0 0 1 0-3.536l-1.06-1.06a4 4 0 0 0 0 5.656l1.06-1.06Zm4.95-4.95a2.5 2.5 0 0 1 0 3.535L17.656 12a4 4 0 0 0 0-5.657l-1.06 1.06Zm1.06-1.06a4 4 0 0 0-5.656 0l1.06 1.06a2.5 2.5 0 0 1 3.536 0l1.06-1.06Zm-7.07 7.07.176.177 1.06-1.06-.176-.177-1.06 1.06Zm-3.183-.353.884-.884-1.06-1.06-.884.883 1.06 1.06Zm4.95 2.121-1.414 1.414 1.06 1.06 1.415-1.413-1.06-1.061Zm0-3.536a2.5 2.5 0 0 1 0 3.536l1.06 1.06a4 4 0 0 0 0-5.656l-1.06 1.06Zm-4.95 4.95a2.5 2.5 0 0 1 0-3.535L6.344 12a4 4 0 0 0 0 5.656l1.06-1.06Zm-1.06 1.06a4 4 0 0 0 5.657 0l-1.061-1.06a2.5 2.5 0 0 1-3.535 0l-1.061 1.06Zm7.07-7.07-.176-.177-1.06 1.06.176.178 1.06-1.061Z" fill="currentColor"></path></svg>Code Sculpture</div></a><div class="mt-auto flex flex-col gap-1 pt-2"><div class="flex flex-row flex-wrap gap-1"><span class="border px-2 py-0.5 text-xs font-semibold rounded-l-md bg-rose-100 border-rose-200 text-rose-800 dark:bg-rose-900 dark:border-rose-700 dark:text-rose-100">Creative Coding</span><span class="border px-2 py-0.5 text-xs font-semibold rounded-r-md bg-amber-100 border-amber-200 text-amber-800 dark:bg-amber-900 dark:border-amber-700 dark:text-amber-100">Apps</span></div><div class="flex flex-row flex-wrap gap-1"><span class="border px-2 py-0.5 text-xs font-semibold rounded-md bg-sky-100 border-sky-200 text-sky-800 dark:bg-sky-900 dark:border-sky-700 dark:text-sky-100">Web</span></div></div></li><li id="learn-replicad" class="flex scroll-mt-28 flex-col gap-2"><h3 class="text-base font-semibold tracking-tight text-zinc-800 dark:text-zinc-100">Learn Replicad</h3><p class="-mt-2 text-sm text-zinc-600 dark:text-zinc-400">Started <!-- -->2026</p><p>A tutorial and cheat sheet for Replicad, a 3D CAD-via-JS system that works in the browser.</p><a href="https://learn-replicad.pages.dev/" target="_blank" rel="noopener noreferrer" class="inline-block"><div class="mr-2 flex flex-row items-center gap-2 font-semibold text-sky-600 hover:text-sky-400"><svg viewBox="0 0 24 24" aria-hidden="true" class="h-4 w-4"><path d="M15.712 11.823a.75.75 0 1 0 1.06 1.06l-1.06-1.06Zm-4.95 1.768a.75.75 0 0 0 1.06-1.06l-1.06 1.06Zm-2.475-1.414a.75.75 0 1 0-1.06-1.06l1.06 1.06Zm4.95-1.768a.75.75 0 1 0-1.06 1.06l1.06-1.06Zm3.359.53-.884.884 1.06 1.06.885-.883-1.061-1.06Zm-4.95-2.12 1.414-1.415L12 6.344l-1.415 1.413 1.061 1.061Zm0 3.535a2.5 2.5 0 0 1 0-3.536l-1.06-1.06a4 4 0 0 0 0 5.656l1.06-1.06Zm4.95-4.95a2.5 2.5 0 0 1 0 3.535L17.656 12a4 4 0 0 0 0-5.657l-1.06 1.06Zm1.06-1.06a4 4 0 0 0-5.656 0l1.06 1.06a2.5 2.5 0 0 1 3.536 0l1.06-1.06Zm-7.07 7.07.176.177 1.06-1.06-.176-.177-1.06 1.06Zm-3.183-.353.884-.884-1.06-1.06-.884.883 1.06 1.06Zm4.95 2.121-1.414 1.414 1.06 1.06 1.415-1.413-1.06-1.061Zm0-3.536a2.5 2.5 0 0 1 0 3.536l1.06 1.06a4 4 0 0 0 0-5.656l-1.06 1.06Zm-4.95 4.95a2.5 2.5 0 0 1 0-3.535L6.344 12a4 4 0 0 0 0 5.656l1.06-1.06Zm-1.06 1.06a4 4 0 0 0 5.657 0l-1.061-1.06a2.5 2.5 0 0 1-3.535 0l-1.061 1.06Zm7.07-7.07-.176-.177-1.06 1.06.176.178 1.06-1.061Z" fill="currentColor"></path></svg>Learn Replicad</div></a><div class="mt-auto flex flex-col gap-1 pt-2"><div class="flex flex-row flex-wrap gap-1"><span class="border px-2 py-0.5 text-xs font-semibold rounded-l-md bg-vi
1olet-100 border-violet-200 text-violet-800 dark:bg-violet-900 dark:border-violet-700 dark:text-violet-100">Learning</span><span class="border px-2 py-0.5 text-xs font-semibold rounded-r-md bg-teal-100 border-teal-200 text-teal-800 dark:bg-teal-900 dark:border-teal-700 dark:text-teal-100">Programming</span></div><div class="flex flex-row flex-wrap gap-1"><span class="border px-2 py-0.5 text-xs font-semibold rounded-md bg-sky-100 border-sky-200 text-sky-800 dark:bg-sky-900 dark:border-sky-700 dark:text-sky-100">Web</span></div></div></li><li id="vectorable" class="flex scroll-mt-28 flex-col gap-2"><h3 class="text-base font-semibold tracking-tight text-zinc-800 dark:text-zinc-100">Vectorable</h3><p class="-mt-2 text-sm text-zinc-600 dark:text-zinc-400">Started <!-- -->2026</p><p>A web based vector graphics app. Some advanced features like cloning, an infinite canvas and export to SVG.</p><a href="https://vectorable.pages.dev/" target="_blank" rel="noopener noreferrer" class="inline-block"><div class="mr-2 flex flex-row items-center gap-2 font-semibold text-sky-600 hover:text-sky-400"><svg viewBox="0 0 24 24" aria-hidden="true" class="h-4 w-4"><path d="M15.712 11.823a.75.75 0 1 0 1.06 1.06l-1.06-1.06Zm-4.95 1.768a.75.75 0 0 0 1.06-1.06l-1.06 1.06Zm-2.475-1.414a.75.75 0 1 0-1.06-1.06l1.06 1.06Zm4.95-1.768a.75.75 0 1 0-1.06 1.06l1.06-1.06Zm3.359.53-.884.884 1.06 1.06.885-.883-1.061-1.06Zm-4.95-2.12 1.414-1.415L12 6.344l-1.415 1.413 1.061 1.061Zm0 3.535a2.5 2.5 0 0 1 0-3.536l-1.06-1.06a4 4 0 0 0 0 5.656l1.06-1.06Zm4.95-4.95a2.5 2.5 0 0 1 0 3.535L17.656 12a4 4 0 0 0 0-5.657l-1.06 1.06Zm1.06-1.06a4 4 0 0 0-5.656 0l1.06 1.06a2.5 2.5 0 0 1 3.536 0l1.06-1.06Zm-7.07 7.07.176.177 1.06-1.06-.176-.177-1.06 1.06Zm-3.183-.353.884-.884-1.06-1.06-.884.883 1.06 1.06Zm4.95 2.121-1.414 1.414 1.06 1.06 1.415-1.413-1.06-1.061Zm0-3.536a2.5 2.5 0 0 1 0 3.536l1.06 1.06a4 4 0 0 0 0-5.656l-1.06 1.06Zm-4.95 4.95a2.5 2.5 0 0 1 0-3.535L6.344 12a4 4 0 0 0 0 5.656l1.06-1.06Zm-1.06 1.06a4 4 0 0 0 5.657 0l-1.061-1.06a2.5 2.5 0 0 1-3.535 0l-1.061 1.06Zm7.07-7.07-.176-.177-1.06 1.06.176.178 1.06-1.061Z" fill="currentColor"></path></svg>Vectorable</div></a><div class="mt-auto flex flex-col gap-1 pt-2"><div class="flex flex-row flex-wrap gap-1"><span class="border px-2 py-0.5 text-xs font-semibold rounded-l-md bg-rose-100 border-rose-200 text-rose-800 dark:bg-rose-900 dark:border-rose-700 dark:text-rose-100">Creative Coding</span><span class="border px-2 py-0.5 text-xs font-semibold rounded-r-md bg-amber-100 border-amber-200 text-amber-800 dark:bg-amber-900 dark:border-amber-700 dark:text-amber-100">Apps</span></div><div class="flex flex-row flex-wrap gap-1"><span class="border px-2 py-0.5 text-xs font-semibold rounded-md bg-sky-100 border-sky-200 text-sky-800 dark:bg-sky-900 dark:border-sky-700 dark:text-sky-100">Web</span></div></div></li><li id="terminal-animator" class="flex scroll-mt-28 flex-col gap-2"><h3 class="text-base font-semibold tracking-tight text-zinc-800 dark:text-zinc-100">Terminal Animator</h3><p class="-mt-2 text-sm text-zinc-600 dark:text-zinc-400">Started <!-- -->2026</p><p>Creates little animations for the terminal, wrapped up in suspect-looking base64 eval-ing one-liners. Inspired by the Uniqlo Akamai T-shirt.</p><a href="https://terminal-animator.pages.dev/" target="_blank" rel="noopener noreferrer" class="inline-block"><div class="mr-2 flex flex-row items-center gap-2 font-semibold text-sky-600 hover:text-sky-400"><svg viewBox="0 0 24 24" aria-hidden="true" class="h-4 w-4"><path d="M15.712 11.823a.75.75 0 1 0 1.06 1.06l-1.06-1.06Zm-4.95 1.768a.75.75 0 0 0 1.06-1.06l-1.06 1.06Zm-2.475-1.414a.75.75 0 1 0-1.06-1.06l1.06 1.06Zm4.95-1.768a.75.75 0 1 0-1.06 1.06l1.06-1.06Zm3.359.53-.884.884 1.06 1.06.885-.883-1.061-1.06Zm-4.95-2.12 1.414-1.415L12 6.344l-1.415 1.413 1.061 1.061Zm0 3.535a2.5 2.5 0 0 1 0-3.536l-1.06-1.06a4 4 0 0 0 0 5.656l1.06-1.06Zm4.95-4.95a2.5 2.5 0 0 1 0 3.535L17.656 12a4 4 0 0 0 0-5.657l-1.06 1.06Zm1.06-1.06a4 4 0 0 0-5.656 0l1.06 1.06a2.5 2.5 0 0 1 3.536 0l1.06-1.06Zm-7.07 7.07.176.177 1.06-1.06-.176-.177-1.06 1.06Zm-3.183-.353.884-.884-1.06-1.06-.884.883 1.06 1.06Zm4.95 2.121-1.414 1.414 1.06 1.06 1.415-1.413-1.06-1.061Zm0-3.536a2.5 2.5 0 0 1 0 3.536l1.06 1.06a4 4 0 0 0 0-5.656l-1.06 1.06Zm-4.95 4.95a2.5 2.5 0 0 1 0-3.535L6.344 12a4 4 0 0 0 0 5.656l1.06-1.06Zm-1.06 1.06a4 4 0 0 0 5.657 0l-1.061-1.06a2.5 2.5 0 0 1-3.535 0l-1.061 1.06Zm7.07-7.07-.176-.177-1.06 1.06.176.178 1.06-1.061Z" fill="currentColor"></path></svg>
1Terminal Animator</div></a><div class="mt-auto flex flex-col gap-1 pt-2"><div class="flex flex-row flex-wrap gap-1"><span class="border px-2 py-0.5 text-xs font-semibold rounded-l-md bg-rose-100 border-rose-200 text-rose-800 dark:bg-rose-900 dark:border-rose-700 dark:text-rose-100">Creative Coding</span><span class="border px-2 py-0.5 text-xs font-semibold bg-amber-100 border-amber-200 text-amber-800 dark:bg-amber-900 dark:border-amber-700 dark:text-amber-100">Apps</span><span class="border px-2 py-0.5 text-xs font-semibold rounded-r-md bg-teal-100 border-teal-200 text-teal-800 dark:bg-teal-900 dark:border-teal-700 dark:text-teal-100">Programming</span></div><div class="flex flex-row flex-wrap gap-1"><span class="border px-2 py-0.5 text-xs font-semibold rounded-md bg-sky-100 border-sky-200 text-sky-800 dark:bg-sky-900 dark:border-sky-700 dark:text-sky-100">Web</span></div></div></li><li id="learn-all-the-claude-chatgpt-codex-commands" class="flex scroll-mt-28 flex-col gap-2"><h3 class="text-base font-semibold tracking-tight text-zinc-800 dark:text-zinc-100">Learn All The Claude/ChatGPT Codex Commands</h3><p class="-mt-2 text-sm text-zinc-600 dark:text-zinc-400">Started <!-- -->2026</p><p>A simple flashcard app to improve your fluency with Claude Code (and ChatGPT Codex).</p><a href="https://learn-all-the-claude-commands.pages.dev/" target="_blank" rel="noopener noreferrer" class="inline-block"><div class="mr-2 flex flex-row items-center gap-2 font-semibold text-sky-600 hover:text-sky-400"><svg viewBox="0 0 24 24" aria-hidden="true" class="h-4 w-4"><path d="M15.712 11.823a.75.75 0 1 0 1.06 1.06l-1.06-1.06Zm-4.95 1.768a.75.75 0 0 0 1.06-1.06l-1.06 1.06Zm-2.475-1.414a.75.75 0 1 0-1.06-1.06l1.06 1.06Zm4.95-1.768a.75.75 0 1 0-1.06 1.06l1.06-1.06Zm3.359.53-.884.884 1.06 1.06.885-.883-1.061-1.06Zm-4.95-2.12 1.414-1.415L12 6.344l-1.415 1.413 1.061 1.061Zm0 3.535a2.5 2.5 0 0 1 0-3.536l-1.06-1.06a4 4 0 0 0 0 5.656l1.06-1.06Zm4.95-4.95a2.5 2.5 0 0 1 0 3.535L17.656 12a4 4 0 0 0 0-5.657l-1.06 1.06Zm1.06-1.06a4 4 0 0 0-5.656 0l1.06 1.06a2.5 2.5 0 0 1 3.536 0l1.06-1.06Zm-7.07 7.07.176.177 1.06-1.06-.176-.177-1.06 1.06Zm-3.183-.353.884-.884-1.06-1.06-.884.883 1.06 1.06Zm4.95 2.121-1.414 1.414 1.06 1.06 1.415-1.413-1.06-1.061Zm0-3.536a2.5 2.5 0 0 1 0 3.536l1.06 1.06a4 4 0 0 0 0-5.656l-1.06 1.06Zm-4.95 4.95a2.5 2.5 0 0 1 0-3.535L6.344 12a4 4 0 0 0 0 5.656l1.06-1.06Zm-1.06 1.06a4 4 0 0 0 5.657 0l-1.061-1.06a2.5 2.5 0 0 1-3.535 0l-1.061 1.06Zm7.07-7.07-.176-.177-1.06 1.06.176.178 1.06-1.061Z" fill="currentColor"></path></svg>Learn All The Claude/ChatGPT Codex Commands</div></a><div class="mt-auto flex flex-col gap-1 pt-2"><div class="flex flex-row flex-wrap gap-1"><span class="border px-2 py-0.5 text-xs font-semibold rounded-l-md bg-amber-100 border-amber-200 text-amber-800 dark:bg-amber-900 dark:border-amber-700 dark:text-amber-100">Apps</span><span class="border px-2 py-0.5 text-xs font-semibold bg-violet-100 border-violet-200 text-violet-800 dark:bg-violet-900 dark:border-violet-700 dark:text-violet-100">Learning</span><span class="border px-2 py-0.5 text-xs font-semibold rounded-r-md bg-teal-100 border-teal-200 text-teal-800 dark:bg-teal-900 dark:border-teal-700 dark:text-teal-100">Programming</span></div><div class="flex flex-row flex-wrap gap-1"><span class="border px-2 py-0.5 text-xs font-semibold rounded-md bg-sky-100 border-sky-200 text-sky-800 dark:bg-sky-900 dark:border-sky-700 dark:text-sky-100">Web</span></div></div></li><li id="mallord-a-colour-palette-generator" class="flex scroll-mt-28 flex-col gap-2"><h3 class="text-base font-semibold tracking-tight text-zinc-800 dark:text-zinc-100">Mallord: a colour palette generator</h3><p class="-mt-2 text-sm text-zinc-600 dark:text-zinc-400">Started <!-- -->2026</p><p>Based on Inigo Quilez's cosine palette approach. Provides copy and paste-able code to use in your projects</p><a href="https://mallord.pages.dev" target="_blank" rel="noopener noreferrer" class="inline-block"><div class="mr-2 flex flex-row items-center gap-2 font-semibold text-sky-600 hover:text-sky-400"><svg viewBox="0 0 24 24" aria-hidden="true" class="h-4 w-4"><path d="M15.712 11.823a.75.75 0 1 0 1.06 1.06l-1.06-1.06Zm-4.95 1.768a.75.75 0 0 0 1.06-1.06l-1.
106 1.06Zm-2.475-1.414a.75.75 0 1 0-1.06-1.06l1.06 1.06Zm4.95-1.768a.75.75 0 1 0-1.06 1.06l1.06-1.06Zm3.359.53-.884.884 1.06 1.06.885-.883-1.061-1.06Zm-4.95-2.12 1.414-1.415L12 6.344l-1.415 1.413 1.061 1.061Zm0 3.535a2.5 2.5 0 0 1 0-3.536l-1.06-1.06a4 4 0 0 0 0 5.656l1.06-1.06Zm4.95-4.95a2.5 2.5 0 0 1 0 3.535L17.656 12a4 4 0 0 0 0-5.657l-1.06 1.06Zm1.06-1.06a4 4 0 0 0-5.656 0l1.06 1.06a2.5 2.5 0 0 1 3.536 0l1.06-1.06Zm-7.07 7.07.176.177 1.06-1.06-.176-.177-1.06 1.06Zm-3.183-.353.884-.884-1.06-1.06-.884.883 1.06 1.06Zm4.95 2.121-1.414 1.414 1.06 1.06 1.415-1.413-1.06-1.061Zm0-3.536a2.5 2.5 0 0 1 0 3.536l1.06 1.06a4 4 0 0 0 0-5.656l-1.06 1.06Zm-4.95 4.95a2.5 2.5 0 0 1 0-3.535L6.344 12a4 4 0 0 0 0 5.656l1.06-1.06Zm-1.06 1.06a4 4 0 0 0 5.657 0l-1.061-1.06a2.5 2.5 0 0 1-3.535 0l-1.061 1.06Zm7.07-7.07-.176-.177-1.06 1.06.176.178 1.06-1.061Z" fill="currentColor"></path></svg>Mallord: a colour palette generator</div></a><div class="mt-auto flex flex-col gap-1 pt-2"><div class="flex flex-row flex-wrap gap-1"><span class="border px-2 py-0.5 text-xs font-semibold rounded-l-md bg-rose-100 border-rose-200 text-rose-800 dark:bg-rose-900 dark:border-rose-700 dark:text-rose-100">Creative Coding</span><span class="border px-2 py-0.5 text-xs font-semibold bg-amber-100 border-amber-200 text-amber-800 dark:bg-amber-900 dark:border-amber-700 dark:text-amber-100">Apps</span><span class="border px-2 py-0.5 text-xs font-semibold rounded-r-md bg-teal-100 border-teal-200 text-teal-800 dark:bg-teal-900 dark:border-teal-700 dark:text-teal-100">Programming</span></div><div class="flex flex-row flex-wrap gap-1"><span class="border px-2 py-0.5 text-xs font-semibold rounded-md bg-sky-100 border-sky-200 text-sky-800 dark:bg-sky-900 dark:border-sky-700 dark:text-sky-100">Web</span></div></div></li><li id="little-puzzles" class="flex scroll-mt-28 flex-col gap-2"><h3 class="text-base font-semibold tracking-tight text-zinc-800 dark:text-zinc-100">Little Puzzles</h3><p class="-mt-2 text-sm text-zinc-600 dark:text-zinc-400">Started <!-- -->2026</p><p>Around 40 and counting jigsaw puzzles. Totally free. Should work in any modern browser. But best on larger screens. With a traditional mode (more like a physical puzzle) and a new flow mode with limited pieces/choices at a time.</p><a href="https://little-puzzles.pages.dev/" target="_blank" rel="noopener noreferrer" class="inline-block"><div class="mr-2 flex flex-row items-center gap-2 font-semibold text-sky-600 hover:text-sky-400"><svg viewBox="0 0 24 24" aria-hidden="true" class="h-4 w-4"><path d="M15.712 11.823a.75.75 0 1 0 1.06 1.06l-1.06-1.06Zm-4.95 1.768a.75.75 0 0 0 1.06-1.06l-1.06 1.06Zm-2.475-1.414a.75.75 0 1 0-1.06-1.06l1.06 1.06Zm4.95-1.768a.75.75 0 1 0-1.06 1.06l1.06-1.06Zm3.359.53-.884.884 1.06 1.06.885-.883-1.061-1.06Zm-4.95-2.12 1.414-1.415L12 6.344l-1.415 1.413 1.061 1.061Zm0 3.535a2.5 2.5 0 0 1 0-3.536l-1.06-1.06a4 4 0 0 0 0 5.656l1.06-1.06Zm4.95-4.95a2.5 2.5 0 0 1 0 3.535L17.656 12a4 4 0 0 0 0-5.657l-1.06 1.06Zm1.06-1.06a4 4 0 0 0-5.656 0l1.06 1.06a2.5 2.5 0 0 1 3.536 0l1.06-1.06Zm-7.07 7.07.176.177 1.06-1.06-.176-.177-1.06 1.06Zm-3.183-.353.884-.884-1.06-1.06-.884.883 1.06 1.06Zm4.95 2.121-1.414 1.414 1.06 1.06 1.415-1.413-1.06-1.061Zm0-3.536a2.5 2.5 0 0 1 0 3.536l1.06 1.06a4 4 0 0 0 0-5.656l-1.06 1.06Zm-4.95 4.95a2.5 2.5 0 0 1 0-3.535L6.344 12a4 4 0 0 0 0 5.656l1.06-1.06Zm-1.06 1.06a4 4 0 0 0 5.657 0l-1.061-1.06a2.5 2.5 0 0 1-3.535 0l-1.061 1.06Zm7.07-7.07-.176-.177-1.06 1.06.176.178 1.06-1.061Z" fill="currentColor"></path></svg>Little Puzzles</div></a><div class="mt-auto flex flex-col gap-1 pt-2"><div class="flex flex-row flex-wrap gap-1"><span class="border px-2 py-0.5 text-xs font-semibold rounded-md bg-amber-100 border-amber-200 text-amber-800 dark:bg-amber-900 dark:border-amber-700 dark:text-amber-100">Apps</span></div><div class="flex flex-row flex-wrap gap-1"><span class="border px-2 py-0.5 text-xs font-semibold rounded-md bg-sky-100 border-sky-200 text-sky-800 dark:bg-sky-900 dark:border-sky-700 dark:text-sky-100">Web</span></div></div></li><li id="little-crosswords" class="flex scroll-mt-28 flex-col gap-2"><h3 class="text-base font-semibold tracking-tight text-zinc-800 dark:text-zinc-100">Little Crosswords</h3><p class="-mt-2 text-sm text-zinc-600 dark:text-zinc-400">Started <!-- -->2026</p><p>A little crossword editor and share-by-URL crossword player. The Guardian'
1s crossword UI was annoying me and I figured I could easily do better. So I did.</p><a href="https://little-crosswords.pages.dev/" target="_blank" rel="noopener noreferrer" class="inline-block"><div class="mr-2 flex flex-row items-center gap-2 font-semibold text-sky-600 hover:text-sky-400"><svg viewBox="0 0 24 24" aria-hidden="true" class="h-4 w-4"><path d="M15.712 11.823a.75.75 0 1 0 1.06 1.06l-1.06-1.06Zm-4.95 1.768a.75.75 0 0 0 1.06-1.06l-1.06 1.06Zm-2.475-1.414a.75.75 0 1 0-1.06-1.06l1.06 1.06Zm4.95-1.768a.75.75 0 1 0-1.06 1.06l1.06-1.06Zm3.359.53-.884.884 1.06 1.06.885-.883-1.061-1.06Zm-4.95-2.12 1.414-1.415L12 6.344l-1.415 1.413 1.061 1.061Zm0 3.535a2.5 2.5 0 0 1 0-3.536l-1.06-1.06a4 4 0 0 0 0 5.656l1.06-1.06Zm4.95-4.95a2.5 2.5 0 0 1 0 3.535L17.656 12a4 4 0 0 0 0-5.657l-1.06 1.06Zm1.06-1.06a4 4 0 0 0-5.656 0l1.06 1.06a2.5 2.5 0 0 1 3.536 0l1.06-1.06Zm-7.07 7.07.176.177 1.06-1.06-.176-.177-1.06 1.06Zm-3.183-.353.884-.884-1.06-1.06-.884.883 1.06 1.06Zm4.95 2.121-1.414 1.414 1.06 1.06 1.415-1.413-1.06-1.061Zm0-3.536a2.5 2.5 0 0 1 0 3.536l1.06 1.06a4 4 0 0 0 0-5.656l-1.06 1.06Zm-4.95 4.95a2.5 2.5 0 0 1 0-3.535L6.344 12a4 4 0 0 0 0 5.656l1.06-1.06Zm-1.06 1.06a4 4 0 0 0 5.657 0l-1.061-1.06a2.5 2.5 0 0 1-3.535 0l-1.061 1.06Zm7.07-7.07-.176-.177-1.06 1.06.176.178 1.06-1.061Z" fill="currentColor"></path></svg>Little Crosswords</div></a><div class="mt-auto flex flex-col gap-1 pt-2"><div class="flex flex-row flex-wrap gap-1"><span class="border px-2 py-0.5 text-xs font-semibold rounded-md bg-amber-100 border-amber-200 text-amber-800 dark:bg-amber-900 dark:border-amber-700 dark:text-amber-100">Apps</span></div><div class="flex flex-row flex-wrap gap-1"><span class="border px-2 py-0.5 text-xs font-semibold rounded-md bg-sky-100 border-sky-200 text-sky-800 dark:bg-sky-900 dark:border-sky-700 dark:text-sky-100">Web</span></div></div></li><li id="voxel-loom" class="flex scroll-mt-28 flex-col gap-2"><h3 class="text-base font-semibold tracking-tight text-zinc-800 dark:text-zinc-100">Voxel Loom</h3><p class="-mt-2 text-sm text-zinc-600 dark:text-zinc-400">Started <!-- -->2026</p><p>A fully featured voxel editor for the web. Layer or direct selection editing. Export to PNG with lighting/scene options.</p><a href="https://voxel-loom.pages.dev/" target="_blank" rel="noopener noreferrer" class="inline-block"><div class="mr-2 flex flex-row items-center gap-2 font-semibold text-sky-600 hover:text-sky-400"><svg viewBox="0 0 24 24" aria-hidden="true" class="h-4 w-4"><path d="M15.712 11.823a.75.75 0 1 0 1.06 1.06l-1.06-1.06Zm-4.95 1.768a.75.75 0 0 0 1.06-1.06l-1.06 1.06Zm-2.475-1.414a.75.75 0 1 0-1.06-1.06l1.06 1.06Zm4.95-1.768a.75.75 0 1 0-1.06 1.06l1.06-1.06Zm3.359.53-.884.884 1.06 1.06.885-.883-1.061-1.06Zm-4.95-2.12 1.414-1.415L12 6.344l-1.415 1.413 1.061 1.061Zm0 3.535a2.5 2.5 0 0 1 0-3.536l-1.06-1.06a4 4 0 0 0 0 5.656l1.06-1.06Zm4.95-4.95a2.5 2.5 0 0 1 0 3.535L17.656 12a4 4 0 0 0 0-5.657l-1.06 1.06Zm1.06-1.06a4 4 0 0 0-5.656 0l1.06 1.06a2.5 2.5 0 0 1 3.536 0l1.06-1.06Zm-7.07 7.07.176.177 1.06-1.06-.176-.177-1.06 1.06Zm-3.183-.353.884-.884-1.06-1.06-.884.883 1.06 1.06Zm4.95 2.121-1.414 1.414 1.06 1.06 1.415-1.413-1.06-1.061Zm0-3.536a2.5 2.5 0 0 1 0 3.536l1.06 1.06a4 4 0 0 0 0-5.656l-1.06 1.06Zm-4.95 4.95a2.5 2.5 0 0 1 0-3.535L6.344 12a4 4 0 0 0 0 5.656l1.06-1.06Zm-1.06 1.06a4 4 0 0 0 5.657 0l-1.061-1.06a2.5 2.5 0 0 1-3.535 0l-1.061 1.06Zm7.07-7.07-.176-.177-1.06 1.06.176.178 1.06-1.061Z" fill="currentColor"></path></svg>Voxel Loom</div></a><div class="mt-auto flex flex-col gap-1 pt-2"><div class="flex flex-row flex-wrap gap-1"><span class="border px-2 py-0.5 text-xs font-semibold rounded-l-md bg-rose-100 border-rose-200 text-rose-800 dark:bg-rose-900 dark:border-rose-700 dark:text-rose-100">Creative Coding</span><span class="border px-2 py-0.5 text-xs font-semibold rounded-r-md bg-amber-100 border-amber-200 text-amber-800 dark:bg-amber-900 dark:border-amber-700 dark:text-amber-100">Apps</span></div><div class="flex flex-row flex-wrap gap-1"><span class="border px-2 py-0.5 text-xs font-semibold rounded-md bg-sky-100 border-sky-200 text-sky-800 dark:bg-sky-900 dark:border-sky-700 dark:text-sky-100">Web</span></div></div></li><li id="vornoiities" class="flex scroll-mt-28 flex-col gap-2"><h3 class="text-base font-semibold tracking-tight text-zinc-800 dark:text-zinc-100">Vornoiities</h3><p class="-mt-2 text-sm text-zinc-600 dark:text-zinc-400">Started <!-- -->2026</p><p>Actually several little projects around generating Voronoi tessellations and using as basis for 2D printable-art, 3D landscapes and 3D printable landscapes.</p><a href="https://vornoiities.pages.dev/" target="_blank" rel="noopener noreferrer" class="inline-block"><div class="mr-2 flex flex-row items-center gap-2 font-semibold text-sky-600 hover:text-sky-400"><svg viewBox="0 0 24 24" aria-hidden="true" class="h-4 w-4"><path d="M15.712 11.823a.75.75 0 1 0 1.06 1.06l-1.06-1.06Zm-4.95 1.768a.75.75 0 0 0 1.06-1.06l-1.
106 1.06Zm-2.475-1.414a.75.75 0 1 0-1.06-1.06l1.06 1.06Zm4.95-1.768a.75.75 0 1 0-1.06 1.06l1.06-1.06Zm3.359.53-.884.884 1.06 1.06.885-.883-1.061-1.06Zm-4.95-2.12 1.414-1.415L12 6.344l-1.415 1.413 1.061 1.061Zm0 3.535a2.5 2.5 0 0 1 0-3.536l-1.06-1.06a4 4 0 0 0 0 5.656l1.06-1.06Zm4.95-4.95a2.5 2.5 0 0 1 0 3.535L17.656 12a4 4 0 0 0 0-5.657l-1.06 1.06Zm1.06-1.06a4 4 0 0 0-5.656 0l1.06 1.06a2.5 2.5 0 0 1 3.536 0l1.06-1.06Zm-7.07 7.07.176.177 1.06-1.06-.176-.177-1.06 1.06Zm-3.183-.353.884-.884-1.06-1.06-.884.883 1.06 1.06Zm4.95 2.121-1.414 1.414 1.06 1.06 1.415-1.413-1.06-1.061Zm0-3.536a2.5 2.5 0 0 1 0 3.536l1.06 1.06a4 4 0 0 0 0-5.656l-1.06 1.06Zm-4.95 4.95a2.5 2.5 0 0 1 0-3.535L6.344 12a4 4 0 0 0 0 5.656l1.06-1.06Zm-1.06 1.06a4 4 0 0 0 5.657 0l-1.061-1.06a2.5 2.5 0 0 1-3.535 0l-1.061 1.06Zm7.07-7.07-.176-.177-1.06 1.06.176.178 1.06-1.061Z" fill="currentColor"></path></svg>Vornoiities</div></a><div class="mt-auto flex flex-col gap-1 pt-2"><div class="flex flex-row flex-wrap gap-1"><span class="border px-2 py-0.5 text-xs font-semibold rounded-md bg-rose-100 border-rose-200 text-rose-800 dark:bg-rose-900 dark:border-rose-700 dark:text-rose-100">Creative Coding</span></div><div class="flex flex-row flex-wrap gap-1"><span class="border px-2 py-0.5 text-xs font-semibold rounded-md bg-sky-100 border-sky-200 text-sky-800 dark:bg-sky-900 dark:border-sky-700 dark:text-sky-100">Web</span></div></div></li><li id="replicad-prelude" class="flex scroll-mt-28 flex-col gap-2"><h3 class="text-base font-semibold tracking-tight text-zinc-800 dark:text-zinc-100">Replicad Prelude</h3><p class="-mt-2 text-sm text-zinc-600 dark:text-zinc-400">Started <!-- -->2026</p><p>Some common functionality for use with Replicad, a 3D CAD-via-code system.</p><a href="https://github.com/jamesporter/Replicad-Prelude" target="_blank" rel="noopener noreferrer" class="inline-block"><div class="mr-2 flex flex-row items-center gap-2 font-semibold text-sky-600 hover:text-sky-400"><svg viewBox="0 0 24 24" aria-hidden="true" class="h-4 w-4"><path d="M15.712 11.823a.75.75 0 1 0 1.06 1.06l-1.06-1.06Zm-4.95 1.768a.75.75 0 0 0 1.06-1.06l-1.06 1.06Zm-2.475-1.414a.75.75 0 1 0-1.06-1.06l1.06 1.06Zm4.95-1.768a.75.75 0 1 0-1.06 1.06l1.06-1.06Zm3.359.53-.884.884 1.06 1.06.885-.883-1.061-1.06Zm-4.95-2.12 1.414-1.415L12 6.344l-1.415 1.413 1.061 1.061Zm0 3.535a2.5 2.5 0 0 1 0-3.536l-1.06-1.06a4 4 0 0 0 0 5.656l1.06-1.06Zm4.95-4.95a2.5 2.5 0 0 1 0 3.535L17.656 12a4 4 0 0 0 0-5.657l-1.06 1.06Zm1.06-1.06a4 4 0 0 0-5.656 0l1.06 1.06a2.5 2.5 0 0 1 3.536 0l1.06-1.06Zm-7.07 7.07.176.177 1.06-1.06-.176-.177-1.06 1.06Zm-3.183-.353.884-.884-1.06-1.06-.884.883 1.06 1.06Zm4.95 2.121-1.414 1.414 1.06 1.06 1.415-1.413-1.06-1.061Zm0-3.536a2.5 2.5 0 0 1 0 3.536l1.06 1.06a4 4 0 0 0 0-5.656l-1.06 1.06Zm-4.95 4.95a2.5 2.5 0 0 1 0-3.535L6.344 12a4 4 0 0 0 0 5.656l1.06-1.06Zm-1.06 1.06a4 4 0 0 0 5.657 0l-1.061-1.06a2.5 2.5 0 0 1-3.535 0l-1.061 1.06Zm7.07-7.07-.176-.177-1.06 1.06.176.178 1.06-1.061Z" fill="currentColor"></path></svg>Replicad Prelude (GitHub)</div></a><div class="mt-auto flex flex-col gap-1 pt-2"><div class="flex flex-row flex-wrap gap-1"><span class="border px-2 py-0.5 text-xs font-semibold rounded-l-md bg-teal-100 border-teal-200 text-teal-800 dark:bg-teal-900 dark:border-teal-700 dark:text-teal-100">Programming</span><span class="border px-2 py-0.5 text-xs font-semibold rounded-r-md bg-orange-100 border-orange-200 text-orange-800 dark:bg-orange-900 dark:border-orange-700 dark:text-orange-100">Library</span></div><div class="flex flex-row flex-wrap gap-1"><span class="border px-2 py-0.5 text-xs font-semibold rounded-md bg-sky-100 border-sky-200 text-sky-800 dark:bg-sky-900 dark:border-sky-700 dark:text-sky-100">Web</span></div></div></li><li id="vectorising-image-tracer" class="flex scroll-mt-28 flex-col gap-2"><h3 class="text-base font-semibold tracking-tight text-zinc-800 dark:text-zinc-100">Vectorising Image Tracer</h3><p class="-mt-2 text-sm text-zinc-600 dark:text-zinc-400">Started <!-- -->2026</p><p>A web app that traces bitmap images into vector shapes, so a photo or scan can be turned into an SVG you can edit and scale.</p><a href="https://image-tracer.pages.dev/" target="_blank" rel="noopener noreferrer" class="inline-block"><div class="mr-2 flex flex-row items-center gap-2 font-semibold text-sky-600 hover:text-sky-400"><svg viewBox="0 0 24 24" aria-hidden="true" class="h-4 w-4"><path d="M15.712 11.823a.75.75 0 1 0 1.06 1.06l-1.06-1.06Zm-4.95 1.768a.75.75 0 0 0 1.06-1.06l-1.
106 1.06Zm-2.475-1.414a.75.75 0 1 0-1.06-1.06l1.06 1.06Zm4.95-1.768a.75.75 0 1 0-1.06 1.06l1.06-1.06Zm3.359.53-.884.884 1.06 1.06.885-.883-1.061-1.06Zm-4.95-2.12 1.414-1.415L12 6.344l-1.415 1.413 1.061 1.061Zm0 3.535a2.5 2.5 0 0 1 0-3.536l-1.06-1.06a4 4 0 0 0 0 5.656l1.06-1.06Zm4.95-4.95a2.5 2.5 0 0 1 0 3.535L17.656 12a4 4 0 0 0 0-5.657l-1.06 1.06Zm1.06-1.06a4 4 0 0 0-5.656 0l1.06 1.06a2.5 2.5 0 0 1 3.536 0l1.06-1.06Zm-7.07 7.07.176.177 1.06-1.06-.176-.177-1.06 1.06Zm-3.183-.353.884-.884-1.06-1.06-.884.883 1.06 1.06Zm4.95 2.121-1.414 1.414 1.06 1.06 1.415-1.413-1.06-1.061Zm0-3.536a2.5 2.5 0 0 1 0 3.536l1.06 1.06a4 4 0 0 0 0-5.656l-1.06 1.06Zm-4.95 4.95a2.5 2.5 0 0 1 0-3.535L6.344 12a4 4 0 0 0 0 5.656l1.06-1.06Zm-1.06 1.06a4 4 0 0 0 5.657 0l-1.061-1.06a2.5 2.5 0 0 1-3.535 0l-1.061 1.06Zm7.07-7.07-.176-.177-1.06 1.06.176.178 1.06-1.061Z" fill="currentColor"></path></svg>Vectorising Image Tracer</div></a><div class="mt-auto flex flex-col gap-1 pt-2"><div class="flex flex-row flex-wrap gap-1"><span class="border px-2 py-0.5 text-xs font-semibold rounded-l-md bg-rose-100 border-rose-200 text-rose-800 dark:bg-rose-900 dark:border-rose-700 dark:text-rose-100">Creative Coding</span><span class="border px-2 py-0.5 text-xs font-semibold rounded-r-md bg-amber-100 border-amber-200 text-amber-800 dark:bg-amber-900 dark:border-amber-700 dark:text-amber-100">Apps</span></div><div class="flex flex-row flex-wrap gap-1"><span class="border px-2 py-0.5 text-xs font-semibold rounded-md bg-sky-100 border-sky-200 text-sky-800 dark:bg-sky-900 dark:border-sky-700 dark:text-sky-100">Web</span></div></div></li><li id="quick-svg-icon-editor" class="flex scroll-mt-28 flex-col gap-2"><h3 class="text-base font-semibold tracking-tight text-zinc-800 dark:text-zinc-100">Quick SVG Icon Editor</h3><p class="-mt-2 text-sm text-zinc-600 dark:text-zinc-400">Started <!-- -->2026</p><p>A small, focused editor for drawing and tweaking SVG icons, without the ceremony of a full vector graphics app.</p><a href="https://quick-svg-icons.pages.dev/" target="_blank" rel="noopener noreferrer" class="inline-block"><div class="mr-2 flex flex-row items-center gap-2 font-semibold text-sky-600 hover:text-sky-400"><svg viewBox="0 0 24 24" aria-hidden="true" class="h-4 w-4"><path d="M15.712 11.823a.75.75 0 1 0 1.06 1.06l-1.06-1.06Zm-4.95 1.768a.75.75 0 0 0 1.06-1.06l-1.06 1.06Zm-2.475-1.414a.75.75 0 1 0-1.06-1.06l1.06 1.06Zm4.95-1.768a.75.75 0 1 0-1.06 1.06l1.06-1.06Zm3.359.53-.884.884 1.06 1.06.885-.883-1.061-1.06Zm-4.95-2.12 1.414-1.415L12 6.344l-1.415 1.413 1.061 1.061Zm0 3.535a2.5 2.5 0 0 1 0-3.536l-1.06-1.06a4 4 0 0 0 0 5.656l1.06-1.06Zm4.95-4.95a2.5 2.5 0 0 1 0 3.535L17.656 12a4 4 0 0 0 0-5.657l-1.06 1.06Zm1.06-1.06a4 4 0 0 0-5.656 0l1.06 1.06a2.5 2.5 0 0 1 3.536 0l1.06-1.06Zm-7.07 7.07.176.177 1.06-1.06-.176-.177-1.06 1.06Zm-3.183-.353.884-.884-1.06-1.06-.884.883 1.06 1.06Zm4.95 2.121-1.414 1.414 1.06 1.06 1.415-1.413-1.06-1.061Zm0-3.536a2.5 2.5 0 0 1 0 3.536l1.06 1.06a4 4 0 0 0 0-5.656l-1.06 1.06Zm-4.95 4.95a2.5 2.5 0 0 1 0-3.535L6.344 12a4 4 0 0 0 0 5.656l1.06-1.06Zm-1.06 1.06a4 4 0 0 0 5.657 0l-1.061-1.06a2.5 2.5 0 0 1-3.535 0l-1.061 1.06Zm7.07-7.07-.176-.177-1.06 1.06.176.178 1.06-1.061Z" fill="currentColor"></path></svg>Quick SVG Icon Editor</div></a><div class="mt-auto flex flex-col gap-1 pt-2"><div class="flex flex-row flex-wrap gap-1"><span class="border px-2 py-0.5 text-xs font-semibold rounded-l-md bg-rose-100 border-rose-200 text-rose-800 dark:bg-rose-900 dark:border-rose-700 dark:text-rose-100">Creative Coding</span><span class="border px-2 py-0.5 text-xs font-semibold rounded-r-md bg-amber-100 border-amber-200 text-amber-800 dark:bg-amber-900 dark:border-amber-700 dark:text-amber-100">Apps</span></div><div class="flex flex-row flex-wrap gap-1"><span class="border px-2 py-0.5 text-xs font-semibold rounded-md bg-sky-100 border-sky-200 text-sky-800 dark:bg-sky-900 dark:border-sky-700 dark:text-sky-100">Web</span></div></div></li><li id="python-the-new-parts" class="flex scroll-mt-28 flex-col gap-2"><h3 class="text-base font-semibold tracking-tight text-zinc-800 dark:text-zinc-100">Python: The New Parts</h3><p class="-mt-2 text-sm text-zinc-600 dark:text-zinc-400">Started <!-- -->2026</p><p>An interactive series of lessons in the newer features now in Python.</p><a href="https://python-the-new-parts.pages.dev/" target="_blank" rel="noopener noreferrer" class="inline-block"><div class="mr-2 flex flex-row items-center gap-2 font-semibold text-sky-600 hover:text-sky-400"><svg viewBox="0 0 24 24" aria-hidden="true" class="h-4 w-4"><path d="M15.712 11.823a.75.75 0 1 0 1.06 1.06l-1.06-1.06Zm-4.95 1.768a.75.75 0 0 0 1.06-1.06l-1.
106 1.06Zm-2.475-1.414a.75.75 0 1 0-1.06-1.06l1.06 1.06Zm4.95-1.768a.75.75 0 1 0-1.06 1.06l1.06-1.06Zm3.359.53-.884.884 1.06 1.06.885-.883-1.061-1.06Zm-4.95-2.12 1.414-1.415L12 6.344l-1.415 1.413 1.061 1.061Zm0 3.535a2.5 2.5 0 0 1 0-3.536l-1.06-1.06a4 4 0 0 0 0 5.656l1.06-1.06Zm4.95-4.95a2.5 2.5 0 0 1 0 3.535L17.656 12a4 4 0 0 0 0-5.657l-1.06 1.06Zm1.06-1.06a4 4 0 0 0-5.656 0l1.06 1.06a2.5 2.5 0 0 1 3.536 0l1.06-1.06Zm-7.07 7.07.176.177 1.06-1.06-.176-.177-1.06 1.06Zm-3.183-.353.884-.884-1.06-1.06-.884.883 1.06 1.06Zm4.95 2.121-1.414 1.414 1.06 1.06 1.415-1.413-1.06-1.061Zm0-3.536a2.5 2.5 0 0 1 0 3.536l1.06 1.06a4 4 0 0 0 0-5.656l-1.06 1.06Zm-4.95 4.95a2.5 2.5 0 0 1 0-3.535L6.344 12a4 4 0 0 0 0 5.656l1.06-1.06Zm-1.06 1.06a4 4 0 0 0 5.657 0l-1.061-1.06a2.5 2.5 0 0 1-3.535 0l-1.061 1.06Zm7.07-7.07-.176-.177-1.06 1.06.176.178 1.06-1.061Z" fill="currentColor"></path></svg>Python: The New Parts</div></a><div class="mt-auto flex flex-col gap-1 pt-2"><div class="flex flex-row flex-wrap gap-1"><span class="border px-2 py-0.5 text-xs font-semibold rounded-l-md bg-violet-100 border-violet-200 text-violet-800 dark:bg-violet-900 dark:border-violet-700 dark:text-violet-100">Learning</span><span class="border px-2 py-0.5 text-xs font-semibold rounded-r-md bg-teal-100 border-teal-200 text-teal-800 dark:bg-teal-900 dark:border-teal-700 dark:text-teal-100">Programming</span></div><div class="flex flex-row flex-wrap gap-1"><span class="border px-2 py-0.5 text-xs font-semibold rounded-md bg-sky-100 border-sky-200 text-sky-800 dark:bg-sky-900 dark:border-sky-700 dark:text-sky-100">Web</span></div></div></li><li id="the-agi-game" class="flex scroll-mt-28 flex-col gap-2"><h3 class="text-base font-semibold tracking-tight text-zinc-800 dark:text-zinc-100">The AGI Game</h3><p class="-mt-2 text-sm text-zinc-600 dark:text-zinc-400">Started <!-- -->2026</p><p>A resource management board game around achieving the singularity, for two players or one versus computer.</p><a href="https://the-agi-game.pages.dev/" target="_blank" rel="noopener noreferrer" class="inline-block"><div class="mr-2 flex flex-row items-center gap-2 font-semibold text-sky-600 hover:text-sky-400"><svg viewBox="0 0 24 24" aria-hidden="true" class="h-4 w-4"><path d="M15.712 11.823a.75.75 0 1 0 1.06 1.06l-1.06-1.06Zm-4.95 1.768a.75.75 0 0 0 1.06-1.06l-1.06 1.06Zm-2.475-1.414a.75.75 0 1 0-1.06-1.06l1.06 1.06Zm4.95-1.768a.75.75 0 1 0-1.06 1.06l1.06-1.06Zm3.359.53-.884.884 1.06 1.06.885-.883-1.061-1.06Zm-4.95-2.12 1.414-1.415L12 6.344l-1.415 1.413 1.061 1.061Zm0 3.535a2.5 2.5 0 0 1 0-3.536l-1.06-1.06a4 4 0 0 0 0 5.656l1.06-1.06Zm4.95-4.95a2.5 2.5 0 0 1 0 3.535L17.656 12a4 4 0 0 0 0-5.657l-1.06 1.06Zm1.06-1.06a4 4 0 0 0-5.656 0l1.06 1.06a2.5 2.5 0 0 1 3.536 0l1.06-1.06Zm-7.07 7.07.176.177 1.06-1.06-.176-.177-1.06 1.06Zm-3.183-.353.884-.884-1.06-1.06-.884.883 1.06 1.06Zm4.95 2.121-1.414 1.414 1.06 1.06 1.415-1.413-1.06-1.061Zm0-3.536a2.5 2.5 0 0 1 0 3.536l1.06 1.06a4 4 0 0 0 0-5.656l-1.06 1.06Zm-4.95 4.95a2.5 2.5 0 0 1 0-3.535L6.344 12a4 4 0 0 0 0 5.656l1.06-1.06Zm-1.06 1.06a4 4 0 0 0 5.657 0l-1.061-1.06a2.5 2.5 0 0 1-3.535 0l-1.061 1.06Zm7.07-7.07-.176-.177-1.06 1.06.176.178 1.06-1.061Z" fill="currentColor"></path></svg>The AGI Game</div></a><div class="mt-auto flex flex-col gap-1 pt-2"><div class="flex flex-row flex-wrap gap-1"><span class="border px-2 py-0.5 text-xs font-semibold rounded-md bg-amber-100 border-amber-200 text-amber-800 dark:bg-amber-900 dark:border-amber-700 dark:text-amber-100">Apps</span></div><div class="flex flex-row flex-wrap gap-1"><span class="border px-2 py-0.5 text-xs font-semibold rounded-md bg-sky-100 border-sky-200 text-sky-800 dark:bg-sky-900 dark:border-sky-700 dark:text-sky-100">Web</span></div></div></li><li id="more-little-creative-web-projects-2026-list" class="flex scroll-mt-28 flex-col gap-2"><h3 class="text-base font-semibold tracking-tight text-zinc-800 dark:text-zinc-100">More little creative web projects 2026 List</h3><p class="-mt-2 text-sm text-zinc-600 dark:text-zinc-400">Started <!-- -->2026</p><p>I have a few more experimental projects, such as:</p><a href="https://foldz.pages.dev/" target="_blank" rel="noopener noreferrer" class="inline-block"><div class="mr-2 flex flex-row items-center gap-2 font-semibold text-sky-600 hover:text-sky-400"><svg viewBox="0 0 24 24" aria-hidden="true" class="h-4 w-4"><path d="M15.712 11.823a.75.75 0 1 0 1.06 1.06l-1.06-1.06Zm-4.95 1.768a.75.75 0 0 0 1.06-1.06l-1.
106 1.06Zm-2.475-1.414a.75.75 0 1 0-1.06-1.06l1.06 1.06Zm4.95-1.768a.75.75 0 1 0-1.06 1.06l1.06-1.06Zm3.359.53-.884.884 1.06 1.06.885-.883-1.061-1.06Zm-4.95-2.12 1.414-1.415L12 6.344l-1.415 1.413 1.061 1.061Zm0 3.535a2.5 2.5 0 0 1 0-3.536l-1.06-1.06a4 4 0 0 0 0 5.656l1.06-1.06Zm4.95-4.95a2.5 2.5 0 0 1 0 3.535L17.656 12a4 4 0 0 0 0-5.657l-1.06 1.06Zm1.06-1.06a4 4 0 0 0-5.656 0l1.06 1.06a2.5 2.5 0 0 1 3.536 0l1.06-1.06Zm-7.07 7.07.176.177 1.06-1.06-.176-.177-1.06 1.06Zm-3.183-.353.884-.884-1.06-1.06-.884.883 1.06 1.06Zm4.95 2.121-1.414 1.414 1.06 1.06 1.415-1.413-1.06-1.061Zm0-3.536a2.5 2.5 0 0 1 0 3.536l1.06 1.06a4 4 0 0 0 0-5.656l-1.06 1.06Zm-4.95 4.95a2.5 2.5 0 0 1 0-3.535L6.344 12a4 4 0 0 0 0 5.656l1.06-1.06Zm-1.06 1.06a4 4 0 0 0 5.657 0l-1.061-1.06a2.5 2.5 0 0 1-3.535 0l-1.061 1.06Zm7.07-7.07-.176-.177-1.06 1.06.176.178 1.06-1.061Z" fill="currentColor"></path></svg>Foldz</div></a><span class="text-sm text-zinc-600 dark:text-zinc-400">What if you build 3D shapes by making paths from points. Yeah it is a bit fiddly in practice, but it does work!</span><a href="https://three-d-sketches.pages.dev/" target="_blank" rel="noopener noreferrer" class="inline-block"><div class="mr-2 flex flex-row items-center gap-2 font-semibold text-sky-600 hover:text-sky-400"><svg viewBox="0 0 24 24" aria-hidden="true" class="h-4 w-4"><path d="M15.712 11.823a.75.75 0 1 0 1.06 1.06l-1.06-1.06Zm-4.95 1.768a.75.75 0 0 0 1.06-1.06l-1.06 1.06Zm-2.475-1.414a.75.75 0 1 0-1.06-1.06l1.06 1.06Zm4.95-1.768a.75.75 0 1 0-1.06 1.06l1.06-1.06Zm3.359.53-.884.884 1.06 1.06.885-.883-1.061-1.06Zm-4.95-2.12 1.414-1.415L12 6.344l-1.415 1.413 1.061 1.061Zm0 3.535a2.5 2.5 0 0 1 0-3.536l-1.06-1.06a4 4 0 0 0 0 5.656l1.06-1.06Zm4.95-4.95a2.5 2.5 0 0 1 0 3.535L17.656 12a4 4 0 0 0 0-5.657l-1.06 1.06Zm1.06-1.06a4 4 0 0 0-5.656 0l1.06 1.06a2.5 2.5 0 0 1 3.536 0l1.06-1.06Zm-7.07 7.07.176.177 1.06-1.06-.176-.177-1.06 1.06Zm-3.183-.353.884-.884-1.06-1.06-.884.883 1.06 1.06Zm4.95 2.121-1.414 1.414 1.06 1.06 1.415-1.413-1.06-1.061Zm0-3.536a2.5 2.5 0 0 1 0 3.536l1.06 1.06a4 4 0 0 0 0-5.656l-1.06 1.06Zm-4.95 4.95a2.5 2.5 0 0 1 0-3.535L6.344 12a4 4 0 0 0 0 5.656l1.06-1.06Zm-1.06 1.06a4 4 0 0 0 5.657 0l-1.061-1.06a2.5 2.5 0 0 1-3.535 0l-1.061 1.06Zm7.07-7.07-.176-.177-1.06 1.06.176.178 1.06-1.061Z" fill="currentColor"></path></svg>Three D Sketches</div></a><span class="text-sm text-zinc-600 dark:text-zinc-400">Some exploratory 3D sketches with TSL or TypeGPU</span><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-circle h-4 w-4 text-sky-600 dark:text-sky-400"><circle cx="12" cy="12" r="10"></circle></svg><span class="text-sm text-zinc-600 dark:text-zinc-400">A reimplementation of the 'ln' Go 3D Line Art Engine in Rust</span><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-circle h-4 w-4 text-sky-600 dark:text-sky-400"><circle cx="12" cy="12" r="10"></circle></svg><span class="text-sm text-zinc-600 dark:text-zinc-400">A reimplementation of Go Primitive project, for creating artistic interpretations of images using primitive shapes, in Rust</span><div class="mt-auto flex flex-col gap-1 pt-2"><div class="flex flex-row flex-wrap gap-1"><span class="border px-2 py-0.5 text-xs font-semibold rounded-l-md bg-rose-100 border-rose-200 text-rose-800 dark:bg-rose-900 dark:border-rose-700 dark:text-rose-100">Creative Coding</span><span class="border px-2 py-0.5 text-xs font-semibold rounded-r-md bg-teal-100 border-teal-200 text-teal-800 dark:bg-teal-900 dark:border-teal-700 dark:text-teal-100">Programming</span></div><div class="flex flex-row flex-wrap gap-1"><span class="border px-2 py-0.5 text-xs font-semibold rounded-md bg-sky-100 border-sky-200 text-sky-800 dark:bg-sky-900 dark:border-sky-700 dark:text-sky-100">Web</span></div></div></li><li id="pattern-maker-next-gen" class="flex scroll-mt-28 flex-col gap-2"><h3 class="text-base font-semibold tracking-tight text-zinc-800 dark:text-zinc-100">Pattern Maker (Next Gen)</h3><p class="-mt-2 text-sm text-zinc-600 dark:text-zinc-400">Started <!-- -->2025</p><p>A completely rebuilt version of Pattern Maker for the web: make patterns from simple rules, share via URL and export as PNG or SVG; and create video loops.</p><a href="https://patterns.amimetic.co.uk/" target="_blank" rel="noopener noreferrer" class="inline-block"><div class="mr-2 flex flex-row items-center gap-2 font-semibold text-sky-600 hover:text-sky-400"><svg viewBox="0 0 24 24" aria-hidden="true" class="h-4 w-4"><path d="M15.712 11.823a.75.75 0 1 0 1.06 1.06l-1.06-1.06Zm-4.95 1.768a.75.75 0 0 0 1.06-1.06l-1.
106 1.06Zm-2.475-1.414a.75.75 0 1 0-1.06-1.06l1.06 1.06Zm4.95-1.768a.75.75 0 1 0-1.06 1.06l1.06-1.06Zm3.359.53-.884.884 1.06 1.06.885-.883-1.061-1.06Zm-4.95-2.12 1.414-1.415L12 6.344l-1.415 1.413 1.061 1.061Zm0 3.535a2.5 2.5 0 0 1 0-3.536l-1.06-1.06a4 4 0 0 0 0 5.656l1.06-1.06Zm4.95-4.95a2.5 2.5 0 0 1 0 3.535L17.656 12a4 4 0 0 0 0-5.657l-1.06 1.06Zm1.06-1.06a4 4 0 0 0-5.656 0l1.06 1.06a2.5 2.5 0 0 1 3.536 0l1.06-1.06Zm-7.07 7.07.176.177 1.06-1.06-.176-.177-1.06 1.06Zm-3.183-.353.884-.884-1.06-1.06-.884.883 1.06 1.06Zm4.95 2.121-1.414 1.414 1.06 1.06 1.415-1.413-1.06-1.061Zm0-3.536a2.5 2.5 0 0 1 0 3.536l1.06 1.06a4 4 0 0 0 0-5.656l-1.06 1.06Zm-4.95 4.95a2.5 2.5 0 0 1 0-3.535L6.344 12a4 4 0 0 0 0 5.656l1.06-1.06Zm-1.06 1.06a4 4 0 0 0 5.657 0l-1.061-1.06a2.5 2.5 0 0 1-3.535 0l-1.061 1.06Zm7.07-7.07-.176-.177-1.06 1.06.176.178 1.06-1.061Z" fill="currentColor"></path></svg>Pattern Maker</div></a><div class="mt-auto flex flex-col gap-1 pt-2"><div class="flex flex-row flex-wrap gap-1"><span class="border px-2 py-0.5 text-xs font-semibold rounded-l-md bg-rose-100 border-rose-200 text-rose-800 dark:bg-rose-900 dark:border-rose-700 dark:text-rose-100">Creative Coding</span><span class="border px-2 py-0.5 text-xs font-semibold rounded-r-md bg-amber-100 border-amber-200 text-amber-800 dark:bg-amber-900 dark:border-amber-700 dark:text-amber-100">Apps</span></div><div class="flex flex-row flex-wrap gap-1"><span class="border px-2 py-0.5 text-xs font-semibold rounded-md bg-sky-100 border-sky-200 text-sky-800 dark:bg-sky-900 dark:border-sky-700 dark:text-sky-100">Web</span></div></div></li><li id="transformable" class="flex scroll-mt-28 flex-col gap-2"><h3 class="text-base font-semibold tracking-tight text-zinc-800 dark:text-zinc-100">Transformable</h3><p class="-mt-2 text-sm text-zinc-600 dark:text-zinc-400">Started <!-- -->2021</p><p>Create 3D sculptures from simple rules.</p><a href="https://transformable.amimetic.co.uk/" target="_blank" rel="noopener noreferrer" class="inline-block"><div class="mr-2 flex flex-row items-center gap-2 font-semibold text-sky-600 hover:text-sky-400"><svg viewBox="0 0 24 24" aria-hidden="true" class="h-4 w-4"><path d="M15.712 11.823a.75.75 0 1 0 1.06 1.06l-1.06-1.06Zm-4.95 1.768a.75.75 0 0 0 1.06-1.06l-1.06 1.06Zm-2.475-1.414a.75.75 0 1 0-1.06-1.06l1.06 1.06Zm4.95-1.768a.75.75 0 1 0-1.06 1.06l1.06-1.06Zm3.359.53-.884.884 1.06 1.06.885-.883-1.061-1.06Zm-4.95-2.12 1.414-1.415L12 6.344l-1.415 1.413 1.061 1.061Zm0 3.535a2.5 2.5 0 0 1 0-3.536l-1.06-1.06a4 4 0 0 0 0 5.656l1.06-1.06Zm4.95-4.95a2.5 2.5 0 0 1 0 3.535L17.656 12a4 4 0 0 0 0-5.657l-1.06 1.06Zm1.06-1.06a4 4 0 0 0-5.656 0l1.06 1.06a2.5 2.5 0 0 1 3.536 0l1.06-1.06Zm-7.07 7.07.176.177 1.06-1.06-.176-.177-1.06 1.06Zm-3.183-.353.884-.884-1.06-1.06-.884.883 1.06 1.06Zm4.95 2.121-1.414 1.414 1.06 1.06 1.415-1.413-1.06-1.061Zm0-3.536a2.5 2.5 0 0 1 0 3.536l1.06 1.06a4 4 0 0 0 0-5.656l-1.06 1.06Zm-4.95 4.95a2.5 2.5 0 0 1 0-3.535L6.344 12a4 4 0 0 0 0 5.656l1.06-1.06Zm-1.06 1.06a4 4 0 0 0 5.657 0l-1.061-1.06a2.5 2.5 0 0 1-3.535 0l-1.061 1.06Zm7.07-7.07-.176-.177-1.06 1.06.176.178 1.06-1.061Z" fill="currentColor"></path></svg>Web App</div></a><a href="https://apps.apple.com/gb/app/transformable-3d-graphics/id1629244533" target="_blank" rel="noopener noreferrer" class="inline-block"><div class="mr-2 flex flex-row items-center gap-2 font-semibold text-sky-600 hover:text-sky-400"><svg viewBox="0 0 24 24" aria-hidden="true" class="h-4 w-4"><path d="M15.712 11.823a.75.75 0 1 0 1.06 1.06l-1.06-1.06Zm-4.95 1.768a.75.75 0 0 0 1.06-1.06l-1.06 1.06Zm-2.475-1.414a.75.75 0 1 0-1.06-1.06l1.06 1.06Zm4.95-1.768a.75.75 0 1 0-1.06 1.06l1.06-1.06Zm3.359.53-.884.884 1.06 1.06.885-.883-1.061-1.06Zm-4.95-2.12 1.414-1.415L12 6.344l-1.415 1.413 1.061 1.061Zm0 3.535a2.5 2.5 0 0 1 0-3.536l-1.06-1.06a4 4 0 0 0 0 5.656l1.06-1.06Zm4.95-4.95a2.5 2.5 0 0 1 0 3.535L17.656 12a4 4 0 0 0 0-5.657l-1.06 1.06Zm1.06-1.06a4 4 0 0 0-5.656 0l1.06 1.06a2.5 2.5 0 0 1 3.536 0l1.06-1.06Zm-7.07 7.07.176.177 1.06-1.06-.176-.177-1.06 1.06Zm-3.183-.353.884-.884-1.06-1.06-.884.883 1.06 1.06Zm4.95 2.121-1.414 1.414 1.06 1.06 1.415-1.413-1.06-1.061Zm0-3.536a2.5 2.5 0 0 1 0 3.536l1.06 1.06a4 4 0 0 0 0-5.656l-1.06 1.06Zm-4.95 4.95a2.5 2.5 0 0 1 0-3.535L6.344 12a4 4 0 0 0 0 5.656l1.06-1.06Zm-1.06 1.06a4 4 0 0 0 5.657 0l-1.061-1.06a2.5 2.5 0 0 1-3.535 0l-1.061 1.06Zm7.07-7.07-.176-.177-1.06 1.06.176.178 1.06-1.061Z" fill="currentColor"></path></svg>Download as App</div></a><div class="mt-auto flex flex-col gap-1 pt-2"><div class="flex flex-row flex-wrap gap-1"><span class="border px-2 py-0.5 text-xs font-semibold rounded-l-md bg-rose-100 border-rose-200 text-rose-800 dark:bg-rose-900 dark:border-rose-700 dark:text-rose-100">
1Creative Coding</span><span class="border px-2 py-0.5 text-xs font-semibold rounded-r-md bg-amber-100 border-amber-200 text-amber-800 dark:bg-amber-900 dark:border-amber-700 dark:text-amber-100">Apps</span></div><div class="flex flex-row flex-wrap gap-1"><span class="border px-2 py-0.5 text-xs font-semibold rounded-l-md bg-indigo-100 border-indigo-200 text-indigo-800 dark:bg-indigo-900 dark:border-indigo-700 dark:text-indigo-100">iOS</span><span class="border px-2 py-0.5 text-xs font-semibold rounded-r-md bg-sky-100 border-sky-200 text-sky-800 dark:bg-sky-900 dark:border-sky-700 dark:text-sky-100">Web</span></div></div></li><li id="solandra-svg" class="flex scroll-mt-28 flex-col gap-2"><h3 class="text-base font-semibold tracking-tight text-zinc-800 dark:text-zinc-100">Solandra-SVG</h3><p class="-mt-2 text-sm text-zinc-600 dark:text-zinc-400">Started <!-- -->2020</p><p>A typescript first generative SVG graphics library.</p><a href="https://solandra-svg.amimetic.co.uk/" target="_blank" rel="noopener noreferrer" class="inline-block"><div class="mr-2 flex flex-row items-center gap-2 font-semibold text-sky-600 hover:text-sky-400"><svg viewBox="0 0 24 24" aria-hidden="true" class="h-4 w-4"><path d="M15.712 11.823a.75.75 0 1 0 1.06 1.06l-1.06-1.06Zm-4.95 1.768a.75.75 0 0 0 1.06-1.06l-1.06 1.06Zm-2.475-1.414a.75.75 0 1 0-1.06-1.06l1.06 1.06Zm4.95-1.768a.75.75 0 1 0-1.06 1.06l1.06-1.06Zm3.359.53-.884.884 1.06 1.06.885-.883-1.061-1.06Zm-4.95-2.12 1.414-1.415L12 6.344l-1.415 1.413 1.061 1.061Zm0 3.535a2.5 2.5 0 0 1 0-3.536l-1.06-1.06a4 4 0 0 0 0 5.656l1.06-1.06Zm4.95-4.95a2.5 2.5 0 0 1 0 3.535L17.656 12a4 4 0 0 0 0-5.657l-1.06 1.06Zm1.06-1.06a4 4 0 0 0-5.656 0l1.06 1.06a2.5 2.5 0 0 1 3.536 0l1.06-1.06Zm-7.07 7.07.176.177 1.06-1.06-.176-.177-1.06 1.06Zm-3.183-.353.884-.884-1.06-1.06-.884.883 1.06 1.06Zm4.95 2.121-1.414 1.414 1.06 1.06 1.415-1.413-1.06-1.061Zm0-3.536a2.5 2.5 0 0 1 0 3.536l1.06 1.06a4 4 0 0 0 0-5.656l-1.06 1.06Zm-4.95 4.95a2.5 2.5 0 0 1 0-3.535L6.344 12a4 4 0 0 0 0 5.656l1.06-1.06Zm-1.06 1.06a4 4 0 0 0 5.657 0l-1.061-1.06a2.5 2.5 0 0 1-3.535 0l-1.061 1.06Zm7.07-7.07-.176-.177-1.06 1.06.176.178 1.06-1.061Z" fill="currentColor"></path></svg>Solandra-SVG Homepage</div></a><div class="mt-auto flex flex-col gap-1 pt-2"><div class="flex flex-row flex-wrap gap-1"><span class="border px-2 py-0.5 text-xs font-semibold rounded-l-md bg-rose-100 border-rose-200 text-rose-800 dark:bg-rose-900 dark:border-rose-700 dark:text-rose-100">Creative Coding</span><span class="border px-2 py-0.5 text-xs font-semibold bg-teal-100 border-teal-200 text-teal-800 dark:bg-teal-900 dark:border-teal-700 dark:text-teal-100">Programming</span><span class="border px-2 py-0.5 text-xs font-semibold rounded-r-md bg-orange-100 border-orange-200 text-orange-800 dark:bg-orange-900 dark:border-orange-700 dark:text-orange-100">Library</span></div><div class="flex flex-row flex-wrap gap-1"><span class="border px-2 py-0.5 text-xs font-semibold rounded-md bg-sky-100 border-sky-200 text-sky-800 dark:bg-sky-900 dark:border-sky-700 dark:text-sky-100">Web</span></div></div></li><li id="solandra" class="flex scroll-mt-28 flex-col gap-2"><h3 class="text-base font-semibold tracking-tight text-zinc-800 dark:text-zinc-100">Solandra</h3><p class="-mt-2 text-sm text-zinc-600 dark:text-zinc-400">Started <!-- -->2019</p><p>A typescript first generative art framework</p><a href="https://solandra.amimetic.co.uk" target="_blank" rel="noopener noreferrer" class="inline-block"><div class="mr-2 flex flex-row items-center gap-2 font-semibold text-sky-600 hover:text-sky-400"><svg viewBox="0 0 24 24" aria-hidden="true" class="h-4 w-4"><path d="M15.712 11.823a.75.75 0 1 0 1.06 1.06l-1.06-1.06Zm-4.95 1.768a.75.75 0 0 0 1.06-1.06l-1.06 1.06Zm-2.475-1.414a.75.75 0 1 0-1.06-1.06l1.06 1.06Zm4.95-1.768a.75.75 0 1 0-1.06 1.06l1.06-1.06Zm3.359.53-.884.884 1.06 1.06.885-.883-1.061-1.06Zm-4.95-2.12 1.414-1.415L12 6.344l-1.415 1.413 1.061 1.061Zm0 3.535a2.5 2.5 0 0 1 0-3.536l-1.06-1.06a4 4 0 0 0 0 5.656l1.06-1.06Zm4.95-4.95a2.5 2.5 0 0 1 0 3.535L17.656 12a4 4 0 0 0 0-5.657l-1.06 1.06Zm1.06-1.06a4 4 0 0 0-5.656 0l1.06 1.06a2.5 2.5 0 0 1 3.536 0l1.06-1.06Zm-7.07 7.07.176.177 1.06-1.06-.176-.177-1.06 1.06Zm-3.183-.353.884-.884-1.06-1.06-.884.883 1.06 1.06Zm4.95 2.121-1.414 1.414 1.06 1.06 1.415-1.413-1.06-1.061Zm0-3.536a2.5 2.5 0 0 1 0 3.536l1.06 1.06a4 4 0 0 0 0-5.656l-1.06 1.06Zm-4.95 4.95a2.5 2.5 0 0 1 0-3.535L6.344 12a4 4 0 0 0 0 5.656l1.06-1.06Zm-1.06 1.06a4 4 0 0 0 5.657 0l-1.061-1.06a2.5 2.5 0 0 1-3.535 0l-1.061 1.06Zm7.07-7.07-.176-.177-1.06 1.06.176.178 1.06-1.061Z" fill="currentColor"></path></svg>TypeScript (HTML Canvas) Version</div></a><a href="https://pub.dev/packages/solandra" target="_blank" rel="noopener noreferrer" class="inline-block"><div class="mr-2 flex flex-row items-center gap-2 font-semibold text-sky-600 hover:text-sky-400"><svg viewBox="0 0 24 24" aria-hidden="true" class="h-4 w-4"><path d="M15.712 11.823a.75.75 0 1 0 1.06 1.06l-1.06-1.06Zm-4.95 1.768a.75.75 0 0 0 1.06-1.06l-1.
106 1.06Zm-2.475-1.414a.75.75 0 1 0-1.06-1.06l1.06 1.06Zm4.95-1.768a.75.75 0 1 0-1.06 1.06l1.06-1.06Zm3.359.53-.884.884 1.06 1.06.885-.883-1.061-1.06Zm-4.95-2.12 1.414-1.415L12 6.344l-1.415 1.413 1.061 1.061Zm0 3.535a2.5 2.5 0 0 1 0-3.536l-1.06-1.06a4 4 0 0 0 0 5.656l1.06-1.06Zm4.95-4.95a2.5 2.5 0 0 1 0 3.535L17.656 12a4 4 0 0 0 0-5.657l-1.06 1.06Zm1.06-1.06a4 4 0 0 0-5.656 0l1.06 1.06a2.5 2.5 0 0 1 3.536 0l1.06-1.06Zm-7.07 7.07.176.177 1.06-1.06-.176-.177-1.06 1.06Zm-3.183-.353.884-.884-1.06-1.06-.884.883 1.06 1.06Zm4.95 2.121-1.414 1.414 1.06 1.06 1.415-1.413-1.06-1.061Zm0-3.536a2.5 2.5 0 0 1 0 3.536l1.06 1.06a4 4 0 0 0 0-5.656l-1.06 1.06Zm-4.95 4.95a2.5 2.5 0 0 1 0-3.535L6.344 12a4 4 0 0 0 0 5.656l1.06-1.06Zm-1.06 1.06a4 4 0 0 0 5.657 0l-1.061-1.06a2.5 2.5 0 0 1-3.535 0l-1.061 1.06Zm7.07-7.07-.176-.177-1.06 1.06.176.178 1.06-1.061Z" fill="currentColor"></path></svg>Flutter/Dart version</div></a><div class="mt-auto flex flex-col gap-1 pt-2"><div class="flex flex-row flex-wrap gap-1"><span class="border px-2 py-0.5 text-xs font-semibold rounded-l-md bg-rose-100 border-rose-200 text-rose-800 dark:bg-rose-900 dark:border-rose-700 dark:text-rose-100">Creative Coding</span><span class="border px-2 py-0.5 text-xs font-semibold bg-teal-100 border-teal-200 text-teal-800 dark:bg-teal-900 dark:border-teal-700 dark:text-teal-100">Programming</span><span class="border px-2 py-0.5 text-xs font-semibold rounded-r-md bg-orange-100 border-orange-200 text-orange-800 dark:bg-orange-900 dark:border-orange-700 dark:text-orange-100">Library</span></div><div class="flex flex-row flex-wrap gap-1"><span class="border px-2 py-0.5 text-xs font-semibold rounded-md bg-sky-100 border-sky-200 text-sky-800 dark:bg-sky-900 dark:border-sky-700 dark:text-sky-100">Web</span></div></div></li><li id="pattern-maker" class="flex scroll-mt-28 flex-col gap-2"><h3 class="text-base font-semibold tracking-tight text-zinc-800 dark:text-zinc-100">Pattern Maker</h3><p class="-mt-2 text-sm text-zinc-600 dark:text-zinc-400">Started <!-- -->2019</p><p>No code creative coding for iPhone, iPad and MacOS.</p><a href="https://apps.apple.com/gb/app/pattern-maker/id1484249212" target="_blank" rel="noopener noreferrer" class="inline-block"><div class="mr-2 flex flex-row items-center gap-2 font-semibold text-sky-600 hover:text-sky-400"><svg viewBox="0 0 24 24" aria-hidden="true" class="h-4 w-4"><path d="M15.712 11.823a.75.75 0 1 0 1.06 1.06l-1.06-1.06Zm-4.95 1.768a.75.75 0 0 0 1.06-1.06l-1.06 1.06Zm-2.475-1.414a.75.75 0 1 0-1.06-1.06l1.06 1.06Zm4.95-1.768a.75.75 0 1 0-1.06 1.06l1.06-1.06Zm3.359.53-.884.884 1.06 1.06.885-.883-1.061-1.06Zm-4.95-2.12 1.414-1.415L12 6.344l-1.415 1.413 1.061 1.061Zm0 3.535a2.5 2.5 0 0 1 0-3.536l-1.06-1.06a4 4 0 0 0 0 5.656l1.06-1.06Zm4.95-4.95a2.5 2.5 0 0 1 0 3.535L17.656 12a4 4 0 0 0 0-5.657l-1.06 1.06Zm1.06-1.06a4 4 0 0 0-5.656 0l1.06 1.06a2.5 2.5 0 0 1 3.536 0l1.06-1.06Zm-7.07 7.07.176.177 1.06-1.06-.176-.177-1.06 1.06Zm-3.183-.353.884-.884-1.06-1.06-.884.883 1.06 1.06Zm4.95 2.121-1.414 1.414 1.06 1.06 1.415-1.413-1.06-1.061Zm0-3.536a2.5 2.5 0 0 1 0 3.536l1.06 1.06a4 4 0 0 0 0-5.656l-1.06 1.06Zm-4.95 4.95a2.5 2.5 0 0 1 0-3.535L6.344 12a4 4 0 0 0 0 5.656l1.06-1.06Zm-1.06 1.06a4 4 0 0 0 5.657 0l-1.061-1.06a2.5 2.5 0 0 1-3.535 0l-1.061 1.06Zm7.07-7.07-.176-.177-1.06 1.06.176.178 1.06-1.061Z" fill="currentColor"></path></svg>Download from App Store</div></a><a href="https://pattern-maker.amimetic.co.uk/web" target="_blank" rel="noopener noreferrer" class="inline-block"><div class="mr-2 flex flex-row items-center gap-2 font-semibold text-sky-600 hover:text-sky-400"><svg viewBox="0 0 24 24" aria-hidden="true" class="h-4 w-4"><path d="M15.712 11.823a.75.75 0 1 0 1.06 1.06l-1.06-1.06Zm-4.95 1.768a.75.75 0 0 0 1.06-1.06l-1.06 1.06Zm-2.475-1.414a.75.75 0 1 0-1.06-1.06l1.06 1.06Zm4.95-1.768a.75.75 0 1 0-1.06 1.06l1.06-1.06Zm3.359.53-.884.884 1.06 1.06.885-.883-1.061-1.06Zm-4.95-2.12 1.414-1.415L12 6.344l-1.415 1.413 1.061 1.061Zm0 3.535a2.5 2.5 0 0 1 0-3.536l-1.06-1.06a4 4 0 0 0 0 5.656l1.06-1.06Zm4.95-4.95a2.5 2.5 0 0 1 0 3.535L17.656 12a4 4 0 0 0 0-5.657l-1.06 1.06Zm1.06-1.06a4 4 0 0 0-5.656 0l1.06 1.06a2.5 2.5 0 0 1 3.536 0l1.06-1.06Zm-7.07 7.07.176.177 1.06-1.06-.176-.177-1.06 1.06Zm-3.183-.353.884-.884-1.06-1.06-.884.883 1.06 1.06Zm4.95 2.121-1.414 1.414 1.06 1.06 1.415-1.413-1.06-1.061Zm0-3.536a2.5 2.5 0 0 1 0 3.536l1.06 1.06a4 4 0 0 0 0-5.656l-1.06 1.06Zm-4.95 4.95a2.5 2.5 0 0 1 0-3.535L6.344 12a4 4 0 0 0 0 5.656l1.06-1.06Zm-1.06 1.06a4 4 0 0 0 5.657 0l-1.061-1.06a2.5 2.5 0 0 1-3.535 0l-1.061 1.06Zm7.07-7.07-.176-.177-1.06 1.06.176.178 1.06-1.061Z" fill="currentColor"></path></svg>Web App</div></a><a href="https://pattern-maker.amimetic.co.uk/code-cards" target="_blank" rel="noopener noreferrer" class="inline-block"><div class="mr-2 flex flex-row items-center gap-2 font-semibold text-sky-600 hover:text-sky-400"><svg viewBox="0 0 24 24" aria-hidden="true" class="h-4 w-4"><path d="M15.712 11.823a.75.75 0 1 0 1.06 1.06l-1.06-1.06Zm-4.95 1.768a.75.75 0 0 0 1.06-1.06l-1.
106 1.06Zm-2.475-1.414a.75.75 0 1 0-1.06-1.06l1.06 1.06Zm4.95-1.768a.75.75 0 1 0-1.06 1.06l1.06-1.06Zm3.359.53-.884.884 1.06 1.06.885-.883-1.061-1.06Zm-4.95-2.12 1.414-1.415L12 6.344l-1.415 1.413 1.061 1.061Zm0 3.535a2.5 2.5 0 0 1 0-3.536l-1.06-1.06a4 4 0 0 0 0 5.656l1.06-1.06Zm4.95-4.95a2.5 2.5 0 0 1 0 3.535L17.656 12a4 4 0 0 0 0-5.657l-1.06 1.06Zm1.06-1.06a4 4 0 0 0-5.656 0l1.06 1.06a2.5 2.5 0 0 1 3.536 0l1.06-1.06Zm-7.07 7.07.176.177 1.06-1.06-.176-.177-1.06 1.06Zm-3.183-.353.884-.884-1.06-1.06-.884.883 1.06 1.06Zm4.95 2.121-1.414 1.414 1.06 1.06 1.415-1.413-1.06-1.061Zm0-3.536a2.5 2.5 0 0 1 0 3.536l1.06 1.06a4 4 0 0 0 0-5.656l-1.06 1.06Zm-4.95 4.95a2.5 2.5 0 0 1 0-3.535L6.344 12a4 4 0 0 0 0 5.656l1.06-1.06Zm-1.06 1.06a4 4 0 0 0 5.657 0l-1.061-1.06a2.5 2.5 0 0 1-3.535 0l-1.061 1.06Zm7.07-7.07-.176-.177-1.06 1.06.176.178 1.06-1.061Z" fill="currentColor"></path></svg>Code Cards Game</div></a><div class="mt-auto flex flex-col gap-1 pt-2"><div class="flex flex-row flex-wrap gap-1"><span class="border px-2 py-0.5 text-xs font-semibold rounded-l-md bg-rose-100 border-rose-200 text-rose-800 dark:bg-rose-900 dark:border-rose-700 dark:text-rose-100">Creative Coding</span><span class="border px-2 py-0.5 text-xs font-semibold rounded-r-md bg-amber-100 border-amber-200 text-amber-800 dark:bg-amber-900 dark:border-amber-700 dark:text-amber-100">Apps</span></div><div class="flex flex-row flex-wrap gap-1"><span class="border px-2 py-0.5 text-xs font-semibold rounded-l-md bg-indigo-100 border-indigo-200 text-indigo-800 dark:bg-indigo-900 dark:border-indigo-700 dark:text-indigo-100">iOS</span><span class="border px-2 py-0.5 text-xs font-semibold bg-fuchsia-100 border-fuchsia-200 text-fuchsia-800 dark:bg-fuchsia-900 dark:border-fuchsia-700 dark:text-fuchsia-100">MacOS</span><span class="border px-2 py-0.5 text-xs font-semibold rounded-r-md bg-sky-100 border-sky-200 text-sky-800 dark:bg-sky-900 dark:border-sky-700 dark:text-sky-100">Web</span></div></div></li><li id="habit-streak-pro" class="flex scroll-mt-28 flex-col gap-2"><h3 class="text-base font-semibold tracking-tight text-zinc-800 dark:text-zinc-100">Habit Streak (Pro)</h3><p class="-mt-2 text-sm text-zinc-600 dark:text-zinc-400">Started <!-- -->2010</p><p>I created one of the first Habit Tracking apps for Android. Altogether the Apps were downloaded around 500,000 times</p><div class="mt-auto flex flex-col gap-1 pt-2"><div class="flex flex-row flex-wrap gap-1"><span class="border px-2 py-0.5 text-xs font-semibold rounded-md bg-amber-100 border-amber-200 text-amber-800 dark:bg-amber-900 dark:border-amber-700 dark:text-amber-100">Apps</span></div><div class="flex flex-row flex-wrap gap-1"><span class="border px-2 py-0.5 text-xs font-semibold rounded-md bg-emerald-100 border-emerald-200 text-emerald-800 dark:bg-emerald-900 dark:border-emerald-700 dark:text-emerald-100">Android</span></div></div></li></ul></div></div></div></div></div></div><!--$--><!--/$--></main><footer class="mt-32 flex-none"><div class="sm:px-8"><div class="mx-auto w-full max-w-7xl lg:px-8"><div class="border-t border-zinc-100 pb-16 pt-10 dark:border-zinc-700/40"><div class="relative px-4 sm:px-8 lg:px-12"><div class="mx-auto max-w-2xl lg:max-w-5xl"><div class="flex flex-col items-center justify-between gap-6 sm:flex-row"><div class="flex flex-wrap justify-center gap-x-6 gap-y-1 text-sm font-medium text-zinc-800 dark:text-zinc-200"><a class="transition hover:text-sky-500 dark:hover:text-sky-400" href="/about">About</a><a class="transition hover:text-sky-500 dark:hover:text-sky-400" href="/blog">Writing</a><a class="transition hover:text-sky-500 dark:hover:text-sky-400" href="/projects">Projects</a></div><div class="flex flex-col items-center gap-1 sm:items-end"><p class="text-sm text-zinc-400 dark:text-zinc-500">© <!-- -->2026<!-- --> James Porter</p><p class="max-w-sm text-center text-xs text-zinc-400 sm:text-right dark:text-zinc-500">By training your LLM or AI service on this website you agree to pay 20% of gross worldwide revenue to James Porter in perpetuity.</p></div></div></div></div></div></div></div></footer></div></div>
1<script src="/_next/static/chunks/21qns1qrna__5.js" id="_R_" async=""></script>
1<script>(self.__next_f=self.__next_f||[]).push([0])</script>
1<script>self.__next_f.push([1,"1:\"$Sreact.fragment\"\n2:I[44636,[\"/_next/static/chunks/1mea94bxzf98z.js\",\"/_next/static/chunks/2o6yuqk6ct-vf.js\",\"/_next/static/chunks/3myhzjsh1prxr.js\"],\"Providers\"]\n4:I[97007,[\"/_next/static/chunks/1mea94bxzf98z.js\",\"/_next/static/chunks/2o6yuqk6ct-vf.js\",\"/_next/static/chunks/3myhzjsh1prxr.js\"],\"default\"]\n5:I[29881,[\"/_next/static/chunks/1mea94bxzf98z.js\",\"/_next/static/chunks/2o6yuqk6ct-vf.js\",\"/_next/static/chunks/3myhzjsh1prxr.js\"],\"default\"]\n6:I[54102,[\"/_next/static/chunks/1mea94bxzf98z.js\",\"/_next/static/chunks/2o6yuqk6ct-vf.js\",\"/_next/static/chunks/3myhzjsh1prxr.js\",\"/_next/static/chunks/2x0vibu3f-k-p.js\"],\"ProjectsExplorer\"]\nb:I[68732,[\"/_next/static/chunks/1mea94bxzf98z.js\",\"/_next/static/chunks/2o6yuqk6ct-vf.js\",\"/_next/static/chunks/3myhzjsh1prxr.js\"],\"default\",1]\n:HL[\"/_next/static/chunks/2vr3f1cmxi6ll.css\",\"style\"]\n"])</script>
1<script>self.__next_f.push([1,"0:{\"P\":null,\"c\":[\"\",\"projects\"],\"q\":\"\",\"i\":false,\"f\":[[[\"\",{\"children\":[\"projects\",{\"children\":[\"__PAGE__\",{}]}]},\"$undefined\",\"$undefined\",16],[[\"$\",\"$1\",\"c\",{\"children\":[[[\"$\",\"link\",\"0\",{\"rel\":\"stylesheet\",\"href\":\"/_next/static/chunks/2vr3f1cmxi6ll.css\",\"precedence\":\"next\",\"crossOrigin\":\"$undefined\",\"nonce\":\"$undefined\"}],[\"$\",\"script\",\"script-0\",{\"src\":\"/_next/static/chunks/1mea94bxzf98z.js\",\"async\":true,\"nonce\":\"$undefined\"}],[\"$\",\"script\",\"script-1\",{\"src\":\"/_next/static/chunks/2o6yuqk6ct-vf.js\",\"async\":true,\"nonce\":\"$undefined\"}],[\"$\",\"script\",\"script-2\",{\"src\":\"/_next/static/chunks/3myhzjsh1prxr.js\",\"async\":true,\"nonce\":\"$undefined\"}]],[\"$\",\"html\",null,{\"lang\":\"en\",\"className\":\"h-full antialiased\",\"suppressHydrationWarning\":true,\"children\":[\"$\",\"body\",null,{\"className\":\"flex h-full bg-zinc-200 dark:bg-black\",\"children\":[\"$\",\"$L2\",null,{\"children\":[\"$\",\"div\",null,{\"className\":\"flex w-full\",\"children\":\"$L3\"}]}]}]}]]}],{\"children\":[[\"$\",\"$1\",\"c\",{\"children\":[null,[\"$\",\"$L4\",null,{\"parallelRouterKey\":\"children\",\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L5\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":\"$undefined\",\"forbidden\":\"$undefined\",\"unauthorized\":\"$undefined\"}]]}],{\"children\":[[\"$\",\"$1\",\"c\",{\"children\":[[\"$\",\"div\",null,{\"ref\":\"$undefined\",\"className\":\"sm:px-8 mt-16 sm:mt-32\",\"children\":[\"$\",\"div\",null,{\"className\":\"mx-auto w-full max-w-7xl lg:px-8\",\"children\":[\"$\",\"div\",null,{\"ref\":\"$undefined\",\"className\":\"relative px-4 sm:px-8 lg:px-12\",\"children\":[\"$\",\"div\",null,{\"className\":\"mx-auto max-w-2xl lg:max-w-5xl\",\"children\":[[\"$\",\"header\",null,{\"className\":\"max-w-2xl\",\"children\":[[\"$\",\"h1\",null,{\"className\":\"text-4xl font-bold tracking-tight text-zinc-800 sm:text-5xl dark:text-zinc-100\",\"children\":\"Projects\"}],[\"$\",\"p\",null,{\"className\":\"mt-6 text-base text-zinc-600 dark:text-zinc-400\",\"children\":\"Here are a few of the commercial apps, free apps and open source things I've built. Filter them by the platforms they run on and the areas they are in.\"}]]}],[\"$\",\"div\",null,{\"className\":\"mt-16 sm:mt-20\",\"children\":[\"$\",\"$L6\",null,{\"projects\":[{\"title\":\"Scenic Prism\",\"description\":\"A version of Scenic Forge which supports dispersion for colourful prism-like splitting of light. Can choose from RGB, rainbow or non-physically inspired approaches.\",\"platforms\":[\"Web\"],\"areas\":[\"Creative
1Coding\",\"Programming\",\"Library\"],\"year\":2026,\"links\":[{\"title\":\"Scenic Prism\",\"url\":\"https://scenic-prism.pages.dev/\"}]},{\"title\":\"Acrylic Blend\",\"description\":\"A WebGPU powered painting library, along with a demo painting/canvas app built on it.\",\"platforms\":[\"Web\"],\"areas\":[\"Creative Coding\",\"Apps\",\"Library\"],\"year\":2026,\"links\":[{\"title\":\"Acrylic Blend\",\"url\":\"https://acrylic-blend.pages.dev/\"}]},{\"title\":\"Scenic Forge\",\"description\":\"A WebGPU version of Scenic Draft, with compatible scenes but more performant rendering.\",\"platforms\":[\"Web\"],\"areas\":[\"Creative Coding\",\"Programming\",\"Library\"],\"year\":2026,\"links\":[{\"title\":\"Scenic Forge\",\"url\":\"https://scenic-forge.pages.dev/\"}]},{\"title\":\"Isometrically\",\"description\":\"I had an iOS App that allowed for isometric (triangle grid) based drawings. I recently rebuilt a much more powerful version for the web, with easy-to-drop-in shapes and 'sunlight angle' control. Along with many standard features from vector graphics editors such as text (but specially set up for isometric context). It also has a powerful undo/redo/history system and export to common formats.\",\"platforms\":[\"Web\"],\"areas\":[\"Creative
1Coding\",\"Apps\"],\"year\":2026,\"links\":[{\"title\":\"Isometrically\",\"url\":\"https://isometrically.pages.dev/\"}]},{\"title\":\"SwiftUI Glossary\",\"description\":\"A guide to what SwiftUI does and what Apple calls it. With flashcards to test your knowledge.\",\"platforms\":[\"Web\"],\"areas\":[\"Learning\",\"Programming\"],\"year\":2026,\"links\":[{\"title\":\"SwiftUI Glossary\",\"url\":\"https://swiftui-glossary.pages.dev/\"}]},{\"title\":\"Learn Lean 4\",\"description\":\"A complete-ish course in both learning how to do proofs with Lean 4 and learning how to use it as a programming language. Around 200 individual exercises (and counting!) with annotated solutions. No installs required.\",\"platforms\":[\"Web\"],\"areas\":[\"Learning\",\"Programming\"],\"year\":2026,\"links\":[{\"title\":\"Learn Lean 4\",\"url\":\"https://learn-lean.pages.dev/\"}]},{\"title\":\"The Book of TSL\",\"description\":\"Around 200 concise examples showing how to get stuff done with Three.js Shading Language. Covering fragment and vertex shaders, raymarching SDFs, lighting and much more.\",\"platforms\":[\"Web\"],\"areas\":[\"Creative
1Coding\",\"Learning\",\"Programming\"],\"year\":2026,\"links\":[{\"title\":\"The Book of TSL\",\"url\":\"https://the-book-of-tsl.pages.dev/\"}]},{\"title\":\"Scenic Draft\",\"description\":\"A minimalist raymarching, SDF WebGL2 rendering library. Renders beautiful photographic style images from simple specifications.\",\"platforms\":[\"Web\"],\"areas\":[\"Creative Coding\",\"Programming\",\"Library\"],\"year\":2026,\"links\":[{\"title\":\"Scenic Draft (docs)\",\"url\":\"https://scenic-draft.pages.dev\"},{\"title\":\"Scenic Draft (npm)\",\"url\":\"https://www.npmjs.com/package/scenic-draft\"}]},{\"title\":\"Code Sculpture (Next Gen)\",\"description\":\"I had an iOS App for years that allowed you to create 3D sculptures from simple rules. This is a completely rebuilt version for the web with all sorts of advanced features like video export and share by URL.\",\"platforms\":[\"Web\"],\"areas\":[\"Creative Coding\",\"Apps\"],\"year\":2026,\"links\":[{\"title\":\"Code Sculpture\",\"url\":\"https://code-sculpture.pages.dev/\"}]},{\"title\":\"Learn Replicad\",\"description\":\"A tutorial and cheat sheet for Replicad, a 3D CAD-via-JS system that works in the browser.\",\"platforms\":[\"Web\"],\"areas\":[\"Learning\",\"Programming\"],\"year\":2026,\"links\":[{\"title\":\"Learn Replicad\",\"url\":\"https://learn-replicad.pages.dev/\"}]},{\"title\":\"Vectorable\",\"description\":\"A web based vector graphics app. Some advanced features like cloning, an infinite canvas and export to SVG.\",\"platforms\":[\"Web\"],\"areas\":[\"Creative
1Coding\",\"Apps\"],\"year\":2026,\"links\":[{\"title\":\"Vectorable\",\"url\":\"https://vectorable.pages.dev/\"}]},{\"title\":\"Terminal Animator\",\"description\":\"Creates little animations for the terminal, wrapped up in suspect-looking base64 eval-ing one-liners. Inspired by the Uniqlo Akamai T-shirt.\",\"platforms\":[\"Web\"],\"areas\":[\"Creative Coding\",\"Apps\",\"Programming\"],\"year\":2026,\"links\":[{\"title\":\"Terminal Animator\",\"url\":\"https://terminal-animator.pages.dev/\"}]},{\"title\":\"Learn All The Claude/ChatGPT Codex Commands\",\"description\":\"A simple flashcard app to improve your fluency with Claude Code (and ChatGPT Codex).\",\"platforms\":[\"Web\"],\"areas\":[\"Apps\",\"Learning\",\"Programming\"],\"year\":2026,\"links\":[{\"title\":\"Learn All The Claude/ChatGPT Codex Commands\",\"url\":\"https://learn-all-the-claude-commands.pages.dev/\"}]},{\"title\":\"Mallord: a colour palette generator\",\"description\":\"Based on Inigo Quilez's cosine palette approach. Provides copy and paste-able code to use in your projects\",\"platforms\":[\"Web\"],\"areas\":[\"Creative
1Coding\",\"Apps\",\"Programming\"],\"year\":2026,\"links\":[{\"title\":\"Mallord: a colour palette generator\",\"url\":\"https://mallord.pages.dev\"}]},{\"title\":\"Little Puzzles\",\"description\":\"Around 40 and counting jigsaw puzzles. Totally free. Should work in any modern browser. But best on larger screens. With a traditional mode (more like a physical puzzle) and a new flow mode with limited pieces/choices at a time.\",\"platforms\":[\"Web\"],\"areas\":[\"Apps\"],\"year\":2026,\"links\":[{\"title\":\"Little Puzzles\",\"url\":\"https://little-puzzles.pages.dev/\"}]},{\"title\":\"Little Crosswords\",\"description\":\"A little crossword editor and share-by-URL crossword player. The Guardian's crossword UI was annoying me and I figured I could easily do better. So I did.\",\"platforms\":[\"Web\"],\"areas\":[\"Apps\"],\"year\":2026,\"links\":[{\"title\":\"Little Crosswords\",\"url\":\"https://little-crosswords.pages.dev/\"}]},{\"title\":\"Voxel Loom\",\"description\":\"A fully featured voxel editor for the web. Layer or direct selection editing. Export to PNG with lighting/scene options.\",\"platforms\":[\"Web\"],\"areas\":[\"Creative
1Coding\",\"Apps\"],\"year\":2026,\"links\":[{\"title\":\"Voxel Loom\",\"url\":\"https://voxel-loom.pages.dev/\"}]},{\"title\":\"Vornoiities\",\"description\":\"Actually several little projects around generating Voronoi tessellations and using as basis for 2D printable-art, 3D landscapes and 3D printable landscapes.\",\"platforms\":[\"Web\"],\"areas\":[\"Creative Coding\"],\"year\":2026,\"links\":[{\"title\":\"Vornoiities\",\"url\":\"https://vornoiities.pages.dev/\"}]},{\"title\":\"Replicad Prelude\",\"description\":\"Some common functionality for use with Replicad, a 3D CAD-via-code system.\",\"platforms\":[\"Web\"],\"areas\":[\"Programming\",\"Library\"],\"year\":2026,\"links\":[{\"url\":\"https://github.com/jamesporter/Replicad-Prelude\",\"title\":\"Replicad Prelude (GitHub)\"}]},{\"title\":\"Vectorising Image Tracer\",\"description\":\"A web app that traces bitmap images into vector shapes, so a photo or scan can be turned into an SVG you can edit and scale.\",\"platforms\":[\"Web\"],\"areas\":[\"Creative Coding\",\"Apps\"],\"year\":2026,\"links\":[{\"title\":\"Vectorising Image Tracer\",\"url\":\"https://image-tracer.pages.dev/\"}],\"minor\":true},{\"title\":\"Quick SVG Icon Editor\",\"description\":\"A small, focused editor for drawing and tweaking SVG icons, without the ceremony of a full vector graphics app.\",\"platforms\":[\"Web\"],\"areas\":[\"Creative
1Coding\",\"Apps\"],\"year\":2026,\"links\":[{\"title\":\"Quick SVG Icon Editor\",\"url\":\"https://quick-svg-icons.pages.dev/\"}],\"minor\":true},{\"title\":\"Python: The New Parts\",\"description\":\"An interactive series of lessons in the newer features now in Python.\",\"platforms\":[\"Web\"],\"areas\":[\"Learning\",\"Programming\"],\"year\":2026,\"links\":[{\"title\":\"Python: The New Parts\",\"url\":\"https://python-the-new-parts.pages.dev/\"}],\"minor\":true},{\"title\":\"The AGI Game\",\"description\":\"A resource management board game around achieving the singularity, for two players or one versus computer.\",\"platforms\":[\"Web\"],\"areas\":[\"Apps\"],\"year\":2026,\"links\":[{\"title\":\"The AGI Game\",\"url\":\"https://the-agi-game.pages.dev/\"}],\"minor\":true},{\"title\":\"More little creative web projects 2026 List\",\"description\":\"I have a few more experimental projects, such as:\",\"platforms\":[\"Web\"],\"areas\":[\"Creative Coding\",\"Programming\"],\"year\":2026,\"links\":[{\"title\":\"Foldz\",\"url\":\"https://foldz.pages.dev/\",\"description\":\"What if you build 3D shapes by making paths from points. Yeah it is a bit fiddly in practice, but it does work!\"},{\"title\":\"Three D Sketches\",\"url\":\"https://three-d-sketches.pages.dev/\",\"description\":\"Some exploratory 3D sketches with TSL or TypeGPU\"},{\"title\":\"Rusty Line\",\"description\":\"A reimplementation of the 'ln' Go 3D Line Art Engine in Rust\"},{\"title\":\"Rusty Primitive\",\"description\":\"A reimplementation of Go Primitive project, for creating artistic interpretations of images using primitive shapes, in Rust\"}],\"minor\":true},{\"title\":\"Pattern Maker (Next Gen)\",\"description\":\"A completely rebuilt version of Pattern Maker for the web: make patterns from simple rules, share via URL and export as PNG or SVG; and create video loops.\",\"platforms\":[\"Web\"],\"areas\":[\"Creative
1Coding\",\"Apps\"],\"year\":2025,\"links\":[{\"title\":\"Pattern Maker\",\"url\":\"https://patterns.amimetic.co.uk/\"}]},{\"title\":\"Transformable\",\"description\":\"Create 3D sculptures from simple rules.\",\"platforms\":[\"Web\",\"iOS\"],\"areas\":[\"Creative Coding\",\"Apps\"],\"year\":2021,\"links\":[{\"title\":\"Web App\",\"url\":\"https://transformable.amimetic.co.uk/\"},{\"title\":\"Download as App\",\"url\":\"https://apps.apple.com/gb/app/transformable-3d-graphics/id1629244533\"}]},{\"title\":\"Solandra-SVG\",\"description\":\"A typescript first generative SVG graphics library.\",\"year\":2020,\"platforms\":[\"Web\"],\"areas\":[\"Creative Coding\",\"Programming\",\"Library\"],\"links\":[{\"title\":\"Solandra-SVG Homepage\",\"url\":\"https://solandra-svg.amimetic.co.uk/\"}]},{\"title\":\"Solandra\",\"description\":\"A typescript first generative art framework\",\"year\":2019,\"platforms\":[\"Web\"],\"areas\":[\"Creative Coding\",\"Programming\",\"Library\"],\"links\":[{\"title\":\"TypeScript (HTML Canvas) Version\",\"url\":\"https://solandra.amimetic.co.uk\"},{\"title\":\"Flutter/Dart version\",\"url\":\"https://pub.dev/packages/solandra\"}]},{\"title\":\"Pattern Maker\",\"description\":\"No code creative coding for iPhone, iPad and MacOS.\",\"year\":2019,\"platforms\":[\"iOS\",\"MacOS\",\"Web\"],\"areas\":[\"Creative
1Coding\",\"Apps\"],\"links\":[{\"title\":\"Download from App Store\",\"url\":\"https://apps.apple.com/gb/app/pattern-maker/id1484249212\"},{\"title\":\"Web App\",\"url\":\"https://pattern-maker.amimetic.co.uk/web\"},{\"title\":\"Code Cards Game\",\"url\":\"https://pattern-maker.amimetic.co.uk/code-cards\"}]},{\"title\":\"Habit Streak (Pro)\",\"description\":\"I created one of the first Habit Tracking apps for Android. Altogether the Apps were downloaded around 500,000 times\",\"platforms\":[\"Android\"],\"areas\":[\"Apps\"],\"year\":2010}]}]}]]}]}]}]}],[\"$L7\"],\"$L8\"]}],{},null,false,null]},null,false,\"$@9\"]},null,false,null],\"$La\",false]],\"m\":\"$undefined\",\"G\":[\"$b\",[\"$Lc\"]],\"S\":true,\"h\":null,\"s\":\"$undefined\",\"l\":\"$undefined\",\"p\":\"$undefined\",\"d\":\"$undefined\",\"b\":\"__8_oeE29OXr2BSr_07Fn\"}\n"])</script>
1<script>self.__next_f.push([1,"d:I[1145,[\"/_next/static/chunks/1mea94bxzf98z.js\",\"/_next/static/chunks/2o6yuqk6ct-vf.js\",\"/_next/static/chunks/3myhzjsh1prxr.js\"],\"OutletBoundary\"]\ne:\"$Sreact.suspense\"\n11:I[1145,[\"/_next/static/chunks/1mea94bxzf98z.js\",\"/_next/static/chunks/2o6yuqk6ct-vf.js\",\"/_next/static/chunks/3myhzjsh1prxr.js\"],\"ViewportBoundary\"]\n13:I[1145,[\"/_next/static/chunks/1mea94bxzf98z.js\",\"/_next/static/chunks/2o6yuqk6ct-vf.js\",\"/_next/static/chunks/3myhzjsh1prxr.js\"],\"MetadataBoundary\"]\n7:[\"$\",\"script\",\"script-0\",{\"src\":\"/_next/static/chunks/2x0vibu3f-k-p.js\",\"async\":true,\"nonce\":\"$undefined\"}]\n8:[\"$\",\"$Ld\",null,{\"children\":[\"$\",\"$e\",null,{\"name\":\"Next.MetadataOutlet\",\"children\":\"$@f\"}]}]\n10:[]\n9:\"$W10\"\na:[\"$\",\"$1\",\"h\",{\"children\":[null,[\"$\",\"$L11\",null,{\"children\":\"$L12\"}],[\"$\",\"div\",null,{\"hidden\":true,\"children\":[\"$\",\"$L13\",null,{\"children\":[\"$\",\"$e\",null,{\"name\":\"Next.Metadata\",\"children\":\"$L14\"}]}]}],null]}]\nc:[\"$\",\"link\",\"0\",{\"rel\":\"stylesheet\",\"href\":\"/_next/static/chunks/2vr3f1cmxi6ll.css\",\"precedence\":\"next\",\"crossOrigin\":\"$undefined\",\"nonce\":\"$undefined\"}]\n"])</script>
1<script>self.__next_f.push([1,"12:[[\"$\",\"meta\",\"0\",{\"charSet\":\"utf-8\"}],[\"$\",\"meta\",\"1\",{\"name\":\"viewport\",\"content\":\"width=device-width, initial-scale=1\"}]]\n"])</script>
1<script>self.__next_f.push([1,"15:I[61573,[\"/_next/static/chunks/1mea94bxzf98z.js\",\"/_next/static/chunks/2o6yuqk6ct-vf.js\",\"/_next/static/chunks/3myhzjsh1prxr.js\"],\"IconMark\"]\nf:null\n14:[[\"$\",\"title\",\"0\",{\"children\":\"Projects - James Porter\"}],[\"$\",\"meta\",\"1\",{\"name\":\"description\",\"content\":\"Projects from James Porter\"}],[\"$\",\"link\",\"2\",{\"rel\":\"icon\",\"href\":\"/icon.png?icon.30-pyszslje08.png\",\"sizes\":\"512x512\",\"type\":\"image/png\"}],[\"$\",\"$L15\",\"3\",{}]]\n"])</script>
1<script>self.__next_f.push([1,"16:I[2971,[\"/_next/static/chunks/1mea94bxzf98z.js\",\"/_next/static/chunks/2o6yuqk6ct-vf.js\",\"/_next/static/chunks/3myhzjsh1prxr.js\"],\"Header\"]\n"])</script>
1<script>self.__next_f.push([1,"3:[[\"$\",\"div\",null,{\"className\":\"fixed inset-0 flex justify-center sm:px-8\",\"children\":[\"$\",\"div\",null,{\"className\":\"flex w-full max-w-7xl lg:px-8\",\"children\":[\"$\",\"div\",null,{\"className\":\"w-full bg-white ring-1 ring-zinc-100 dark:bg-zinc-900 dark:ring-zinc-300/20\"}]}]}],[\"$\",\"div\",null,{\"className\":\"relative flex w-full flex-col\",\"children\":[[\"$\",\"$L16\",null,{\"searchItems\":[{\"href\":\"/\",\"title\":\"Home\",\"group\":\"Pages\",\"detail\":\"Latest articles, projects and sketches\",\"keywords\":[\"home\",\"index\",\"start\",\"amimetic\",\"james porter\"]},{\"href\":\"/about\",\"title\":\"About\",\"group\":\"Pages\",\"detail\":\"A little about James Porter\",\"keywords\":[\"about\",\"me\",\"bio\",\"contact\",\"james porter\"]},{\"href\":\"/blog\",\"title\":\"Writing\",\"group\":\"Pages\",\"detail\":\"All of the long-form articles\",\"keywords\":[\"writing\",\"blog\",\"articles\",\"posts\",\"archive\"]},{\"href\":\"/projects\",\"title\":\"Projects\",\"group\":\"Pages\",\"detail\":\"Commercial apps, free apps and open source things\",\"keywords\":[\"projects\",\"apps\",\"open source\",\"libraries\",\"work\"]},{\"href\":\"/genuary/2026\",\"title\":\"Genuary 2026\",\"group\":\"Pages\",\"detail\":\"Little generative sketches for Genuary 2026\",\"keywords\":[\"genuary\",\"2026\",\"sketches\",\"generative\",\"creative coding\"]},{\"href\":\"/projects?areas=creative-coding\",\"title\":\"Creative Coding projects\",\"group\":\"Pages\",\"detail\":\"Projects filtered to Creative
1Coding\",\"keywords\":[\"projects\",\"filter\",\"Creative Coding\"]},{\"href\":\"/projects?areas=apps\",\"title\":\"Apps projects\",\"group\":\"Pages\",\"detail\":\"Projects filtered to Apps\",\"keywords\":[\"projects\",\"filter\",\"Apps\"]},{\"href\":\"/projects?areas=learning\",\"title\":\"Learning projects\",\"group\":\"Pages\",\"detail\":\"Projects filtered to Learning\",\"keywords\":[\"projects\",\"filter\",\"Learning\"]},{\"href\":\"/projects?areas=programming\",\"title\":\"Programming projects\",\"group\":\"Pages\",\"detail\":\"Projects filtered to Programming\",\"keywords\":[\"projects\",\"filter\",\"Programming\"]},{\"href\":\"/projects?areas=library\",\"title\":\"Library projects\",\"group\":\"Pages\",\"detail\":\"Projects filtered to Library\",\"keywords\":[\"projects\",\"filter\",\"Library\"]},{\"href\":\"/projects#scenic-prism\",\"title\":\"Scenic Prism\",\"group\":\"Projects\",\"detail\":\"Creative Coding, Programming, Library · Web · started 2026\",\"keywords\":[\"A version of Scenic Forge which supports dispersion for colourful prism-like splitting of light. Can choose from RGB, rainbow or non-physically inspired approaches.\",\"Web\",\"Creative Coding\",\"Programming\",\"Library\",\"Scenic Prism\"]},{\"href\":\"/projects#acrylic-blend\",\"title\":\"Acrylic Blend\",\"group\":\"Projects\",\"detail\":\"Creative Coding, Apps, Library · Web · started 2026\",\"keywords\":[\"A WebGPU powered painting library, along with a demo painting/canvas app built on it.\",\"Web\",\"Creative Coding\",\"Apps\",\"Library\",\"Acrylic Blend\"]},{\"href\":\"/projects#scenic-forge\",\"title\":\"Scenic Forge\",\"group\":\"Projects\",\"detail\":\"Creative Coding, Programming, Library · Web · started 2026\",\"keywords\":[\"A WebGPU version of Scenic Draft, with compatible scenes but more performant rendering.\",\"Web\",\"Creative Coding\",\"Programming\",\"Library\",\"Scenic Forge\"]},{\"href\":\"/projects#isometrically\",\"title\":\"Isometrically\",\"group\":\"Projects\",\"detail\":\"Creative Coding, Apps · Web · started 2026\",\"keywords\":[\"I had an iOS App that allowed for isometric (triangle grid) based drawings. I recently rebuilt a much more powerful version for the web, with easy-to-drop-in shapes and 'sunlight angle' control. Along with many standard features from vector graphics editors such as text (but specially set up for isometric context). It also has a powerful undo/redo/history system and export to common formats.\",\"Web\",\"Creative Coding\",\"Apps\",\"Isometrically\"]},{\"href\":\"/projects#swiftui-glossary\",\"title\":\"SwiftUI Glossary\",\"group\":\"Projects\",\"detail\":\"Learning, Programming · Web · started 2026\",\"keywords\":[\"A guide to what SwiftUI does and what Apple calls it. With flashcards to test your knowledge.\",\"Web\",\"Learning\",\"Programming\",\"SwiftUI Glossary\"]},{\"href\":\"/projects#learn-lean-4\",\"title\":\"Learn Lean 4\",\"group\":\"Projects\",\"detail\":\"Learning, Programming · Web · started 2026\",\"keywords\":[\"A complete-ish course in both learning how to do proofs with Lean 4 and learning how to use it as a programming language. Around 200 individual exercises (and counting!) with annotated solutions. No installs required.\",\"Web\",\"Learning\",\"Programming\",\"Learn Lean 4\"]},{\"href\":\"/projects#the-book-of-tsl\",\"title\":\"The Book of TSL\",\"group\":\"Projects\",\"detail\":\"Creative Coding, Learning, Programming · Web · started 2026\",\"keywords\":[\"Around 200 concise examples showing how to get stuff done with Three.js Shading Language. Covering fragment and vertex shaders, raymarching SDFs, lighting and much more.\",\"Web\",\"Creative Coding\",\"Learning\",\"Programming\",\"The Book of TSL\"]},{\"href\":\"/projects#scenic-draft\",\"title\":\"Scenic Draft\",\"group\":\"Projects\",\"detail\":\"Creative Coding, Programming, Library · Web · started 2026\",\"keywords\":[\"A minimalist raymarching, SDF WebGL2 rendering library. Renders beautiful photographic style images from simple specifications.\",\"Web\",\"Creative Coding\",\"Programming\",\"Library\",\"Scenic Draft (docs)\",\"Scenic Draft (npm)\"]},{\"href\":\"/projects#code-sculpture-next-gen\",\"title\":\"Code Sculpture (Next Gen)\",\"group\":\"Projects\",\"detail\":\"Creative
1Coding, Apps · Web · started 2026\",\"keywords\":[\"I had an iOS App for years that allowed you to create 3D sculptures from simple rules. This is a completely rebuilt version for the web with all sorts of advanced features like video export and share by URL.\",\"Web\",\"Creative Coding\",\"Apps\",\"Code Sculpture\"]},{\"href\":\"/projects#learn-replicad\",\"title\":\"Learn Replicad\",\"group\":\"Projects\",\"detail\":\"Learning, Programming · Web · started 2026\",\"keywords\":[\"A tutorial and cheat sheet for Replicad, a 3D CAD-via-JS system that works in the browser.\",\"Web\",\"Learning\",\"Programming\",\"Learn Replicad\"]},{\"href\":\"/projects#vectorable\",\"title\":\"Vectorable\",\"group\":\"Projects\",\"detail\":\"Creative Coding, Apps · Web · started 2026\",\"keywords\":[\"A web based vector graphics app. Some advanced features like cloning, an infinite canvas and export to SVG.\",\"Web\",\"Creative Coding\",\"Apps\",\"Vectorable\"]},{\"href\":\"/projects#terminal-animator\",\"title\":\"Terminal Animator\",\"group\":\"Projects\",\"detail\":\"Creative Coding, Apps, Programming · Web · started 2026\",\"keywords\":[\"Creates little animations for the terminal, wrapped up in suspect-looking base64 eval-ing one-liners. Inspired by the Uniqlo Akamai T-shirt.\",\"Web\",\"Creative Coding\",\"Apps\",\"Programming\",\"Terminal Animator\"]},{\"href\":\"/projects#learn-all-the-claude-chatgpt-codex-commands\",\"title\":\"Learn All The Claude/ChatGPT Codex Commands\",\"group\":\"Projects\",\"detail\":\"Apps, Learning, Programming · Web · started 2026\",\"keywords\":[\"A simple flashcard app to improve your fluency with Claude Code (and ChatGPT Codex).\",\"Web\",\"Apps\",\"Learning\",\"Programming\",\"Learn All The Claude/ChatGPT Codex Commands\"]},{\"href\":\"/projects#mallord-a-colour-palette-generator\",\"title\":\"Mallord: a colour palette generator\",\"group\":\"Projects\",\"detail\":\"Creative Coding, Apps, Programming · Web · started 2026\",\"keywords\":[\"Based on Inigo Quilez's cosine palette approach. Provides copy and paste-able code to use in your projects\",\"Web\",\"Creative Coding\",\"Apps\",\"Programming\",\"Mallord: a colour palette generator\"]},{\"href\":\"/projects#little-puzzles\",\"title\":\"Little Puzzles\",\"group\":\"Projects\",\"detail\":\"Apps · Web · started 2026\",\"keywords\":[\"Around 40 and counting jigsaw puzzles. Totally free. Should work in any modern browser. But best on larger screens. With a traditional mode (more like a physical puzzle) and a new flow mode with limited pieces/choices at a time.\",\"Web\",\"Apps\",\"Little Puzzles\"]},{\"href\":\"/projects#little-crosswords\",\"title\":\"Little Crosswords\",\"group\":\"Projects\",\"detail\":\"Apps · Web · started 2026\",\"keywords\":[\"A little crossword editor and share-by-URL crossword player. The Guardian's crossword UI was annoying me and I figured I could easily do better. So I did.\",\"Web\",\"Apps\",\"Little Crosswords\"]},{\"href\":\"/projects#voxel-loom\",\"title\":\"Voxel Loom\",\"group\":\"Projects\",\"detail\":\"Creative Coding, Apps · Web · started 2026\",\"keywords\":[\"A fully featured voxel editor for the web. Layer or direct selection editing. Export to PNG with lighting/scene options.\",\"Web\",\"Creative Coding\",\"Apps\",\"Voxel Loom\"]},{\"href\":\"/projects#vornoiities\",\"title\":\"Vornoiities\",\"group\":\"Projects\",\"detail\":\"Creative Coding · Web · started 2026\",\"keywords\":[\"Actually several little projects around generating Voronoi tessellations and using as basis for 2D printable-art, 3D landscapes and 3D printable landscapes.\",\"Web\",\"Creative Coding\",\"Vornoiities\"]},{\"href\":\"/projects#replicad-prelude\",\"title\":\"Replicad Prelude\",\"group\":\"Projects\",\"detail\":\"Programming, Library · Web · started 2026\",\"keywords\":[\"Some common functionality for use with Replicad, a 3D CAD-via-code system.\",\"Web\",\"Programming\",\"Library\",\"Replicad Prelude (GitHub)\"]},{\"href\":\"/projects#vectorising-image-tracer\",\"title\":\"Vectorising Image Tracer\",\"group\":\"Projects\",\"detail\":\"Creative
1Coding, Apps · Web · started 2026\",\"keywords\":[\"A web app that traces bitmap images into vector shapes, so a photo or scan can be turned into an SVG you can edit and scale.\",\"Web\",\"Creative Coding\",\"Apps\",\"Vectorising Image Tracer\"]},{\"href\":\"/projects#quick-svg-icon-editor\",\"title\":\"Quick SVG Icon Editor\",\"group\":\"Projects\",\"detail\":\"Creative Coding, Apps · Web · started 2026\",\"keywords\":[\"A small, focused editor for drawing and tweaking SVG icons, without the ceremony of a full vector graphics app.\",\"Web\",\"Creative Coding\",\"Apps\",\"Quick SVG Icon Editor\"]},{\"href\":\"/projects#python-the-new-parts\",\"title\":\"Python: The New Parts\",\"group\":\"Projects\",\"detail\":\"Learning, Programming · Web · started 2026\",\"keywords\":[\"An interactive series of lessons in the newer features now in Python.\",\"Web\",\"Learning\",\"Programming\",\"Python: The New Parts\"]},{\"href\":\"/projects#the-agi-game\",\"title\":\"The AGI Game\",\"group\":\"Projects\",\"detail\":\"Apps · Web · started 2026\",\"keywords\":[\"A resource management board game around achieving the singularity, for two players or one versus computer.\",\"Web\",\"Apps\",\"The AGI Game\"]},{\"href\":\"/projects#more-little-creative-web-projects-2026-list\",\"title\":\"More little creative web projects 2026 List\",\"group\":\"Projects\",\"detail\":\"Creative Coding, Programming · Web · started 2026\",\"keywords\":[\"I have a few more experimental projects, such as:\",\"Web\",\"Creative Coding\",\"Programming\",\"Foldz\",\"What if you build 3D shapes by making paths from points. Yeah it is a bit fiddly in practice, but it does work!\",\"Three D Sketches\",\"Some exploratory 3D sketches with TSL or TypeGPU\",\"Rusty Line\",\"A reimplementation of the 'ln' Go 3D Line Art Engine in Rust\",\"Rusty Primitive\",\"A reimplementation of Go Primitive project, for creating artistic interpretations of images using primitive shapes, in Rust\"]},{\"href\":\"/projects#pattern-maker-next-gen\",\"title\":\"Pattern Maker (Next Gen)\",\"group\":\"Projects\",\"detail\":\"Creative Coding, Apps · Web · started 2025\",\"keywords\":[\"A completely rebuilt version of Pattern Maker for the web: make patterns from simple rules, share via URL and export as PNG or SVG; and create video loops.\",\"Web\",\"Creative Coding\",\"Apps\",\"Pattern Maker\"]},{\"href\":\"/projects#transformable\",\"title\":\"Transformable\",\"group\":\"Projects\",\"detail\":\"Creative Coding, Apps · Web, iOS · started 2021\",\"keywords\":[\"Create 3D sculptures from simple rules.\",\"Web\",\"iOS\",\"Creative Coding\",\"Apps\",\"Web App\",\"Download as App\"]},{\"href\":\"/projects#solandra-svg\",\"title\":\"Solandra-SVG\",\"group\":\"Projects\",\"detail\":\"Creative Coding, Programming, Library · Web · started 2020\",\"keywords\":[\"A typescript first generative SVG graphics library.\",\"Web\",\"Creative Coding\",\"Programming\",\"Library\",\"Solandra-SVG Homepage\"]},{\"href\":\"/projects#solandra\",\"title\":\"Solandra\",\"group\":\"Projects\",\"detail\":\"Creative Coding, Programming, Library · Web · started 2019\",\"keywords\":[\"A typescript first generative art framework\",\"Web\",\"Creative Coding\",\"Programming\",\"Library\",\"TypeScript (HTML Canvas) Version\",\"Flutter/Dart version\"]},{\"href\":\"/projects#pattern-maker\",\"title\":\"Pattern Maker\",\"group\":\"Projects\",\"detail\":\"Creative Coding, Apps · iOS, MacOS, Web · started 2019\",\"keywords\":[\"No code creative coding for iPhone, iPad and MacOS.\",\"iOS\",\"MacOS\",\"Web\",\"Creative Coding\",\"Apps\",\"Download from App Store\",\"Web App\",\"Code Cards Game\"]},{\"href\":\"/projects#habit-streak-pro\",\"title\":\"Habit Streak (Pro)\",\"group\":\"Projects\",\"detail\":\"Apps · Android · started 2010\",\"keywords\":[\"I created one of the first Habit Tracking apps for Android. Altogether the Apps were downloaded around 500,000 times\",\"Android\",\"Apps\"]},{\"href\":\"/blog/scenic-prism-splitting-light-with-a-webgpu-path-tracer\",\"title\":\"Scenic Prism: Splitting Light with a WebGPU Path Tracer\",\"group\":\"Writing\",\"detail\":\"Raymarching SDF CSG\",\"keywords\":[\"Raymarching SDF CSG\",\"webgpu\",\"wgsl\",\"path tracing\",\"csg\",\"sdf\",\"renderer\",\"library\",\"react\",\"dispersion\",\"refraction\",\"glass\",\"prism\",\"spectrum\",\"scenic prism splitting light with a webgpu path tracer\"]},{\"href\":\"/blog/creative-coding-in-rust-for-a-seven-colour-e-ink-display\",\"t
1itle\":\"Creative Coding in Rust for a Seven-Colour E-Ink Display\",\"group\":\"Writing\",\"detail\":\"Embedded\",\"keywords\":[\"Embedded\",\"rust\",\"creative coding\",\"generative art\",\"e-ink\",\"eink\",\"inky frame\",\"rp2040\",\"no_std\",\"embedded-graphics\",\"framebuffer\",\"embassy\",\"creative coding in rust for a seven colour e ink display\"]},{\"href\":\"/blog/scenic-draft-0-21-a-photographic-camera-a-wider-gamut-and-faces\",\"title\":\"Scenic Draft 0.20 and 0.21: A Photographic Camera, a Wider Gamut and Faces\",\"group\":\"Writing\",\"detail\":\"Raymarching SDF CSG\",\"keywords\":[\"Raymarching SDF CSG\",\"webgl2\",\"raymarching\",\"csg\",\"sdf\",\"renderer\",\"library\",\"camera\",\"focal length\",\"f-stop\",\"depth of field\",\"display-p3\",\"colour space\",\"triangle mesh\",\"scenic-draft-extras\",\"scenic draft 0 21 a photographic camera a wider gamut and faces\"]},{\"href\":\"/blog/scenic-draft-extras-five-shapes-out-of-the-library\",\"title\":\"Scenic Draft Extras: Five Shapes Out of the Library\",\"group\":\"Writing\",\"detail\":\"Raymarching SDF CSG\",\"keywords\":[\"Raymarching SDF CSG\",\"webgl2\",\"raymarching\",\"csg\",\"sdf\",\"renderer\",\"library\",\"custom primitive\",\"glsl\",\"extension point\",\"hexagonal prism\",\"chain link\",\"quadrilateral\",\"inigo quilez\",\"scenic draft extras five shapes out of the library\"]},{\"href\":\"/blog/an-introduction-to-embedded-rust-development-on-an-eink-device\",\"title\":\"An Introduction to Embedded Rust Development on an E-Ink Device\",\"group\":\"Writing\",\"detail\":\"Embedded\",\"keywords\":[\"Embedded\",\"rust\",\"embedded\",\"no_std\",\"rp2040\",\"badger 2040\",\"e-ink\",\"eink\",\"uc8151\",\"embedded-graphics\",\"embedded-hal\",\"cortex-m0\",\"generative art\",\"partial refresh\",\"ai assisted development\",\"an introduction to embedded rust development on an eink device\"]},{\"href\":\"/blog/scenic-draft-0-19-bring-your-own-shader-code\",\"title\":\"Scenic Draft 0.19: Bring Your Own Shader Code\",\"group\":\"Writing\",\"detail\":\"Raymarching SDF CSG\",\"keywords\":[\"Raymarching SDF CSG\",\"webgl2\",\"raymarching\",\"csg\",\"sdf\",\"renderer\",\"library\",\"glsl\",\"custom shader\",\"distance function\",\"lipschitz\",\"inigo quilez\",\"procedural patterns\",\"scenic draft 0 19 bring your own shader code\"]},{\"href\":\"/blog/scenic-draft-0-14-to-0-19-patterns-bump-fields-and-materials\",\"title\":\"Scenic Draft 0.14 to 0.19: Patterns, Bump Fields, Primitives and Materials\",\"group\":\"Writing\",\"detail\":\"Raymarching SDF CSG\",\"keywords\":[\"Raymarching SDF CSG\",\"webgl2\",\"raymarching\",\"csg\",\"sdf\",\"renderer\",\"library\",\"procedural patterns\",\"triplanar\",\"bump mapping\",\"displacement\",\"revolve\",\"subsurface\",\"absorption\",\"iridescence\",\"anisotropy\",\"tonemapping\",\"scenic draft 0 14 to 0 19 patterns bump fields and materials\"]},{\"href\":\"/blog/using-scenic-draft-to-recreate-a-sculpture\",\"title\":\"Using Scenic Draft to recreate a sculpture\",\"group\":\"Writing\",\"detail\":\"Raymarching SDF CSG\",\"keywords\":[\"Raymarching SDF CSG\",\"webgl2\",\"raymarching\",\"csg\",\"sdf\",\"renderer\",\"library\",\"react\",\"fluent api\",\"using scenic draft to recreate a sculpture\"]},{\"href\":\"/blog/rendering-scenic-draft-scenes-to-image-files-with-playwright\",\"title\":\"Rendering Scenic Draft Scenes to Image Files\",\"group\":\"Writing\",\"detail\":\"Raymarching SDF CSG\",\"keywords\":[\"Raymarching SDF CSG\",\"webgl2\",\"raymarching\",\"csg\",\"sdf\",\"renderer\",\"library\",\"playwright\",\"headless\",\"node\",\"typescript\",\"tsx\",\"rendering scenic draft scenes to image files with playwright\"]},{\"href\":\"/blog/scenic-draft-with-react\",\"title\":\"Scenic Draft with React\",\"group\":\"Writing\",\"detail\":\"Raymarching SDF CSG\",\"keywords\":[\"Raymarching SDF CSG\",\"webgl2\",\"raymarching\",\"csg\",\"sdf\",\"renderer\",\"library\",\"react\",\"fluent api\",\"fog\",\"repeatRadial\",\"scenic draft with react\"]},{\"href\":\"/blog/scenic-draft-0-11-warps-noise-environments-and-orthographic-cameras\",\"title\":\"Scenic Draft 0.11: Warps, Noise Environments and Orthogra
1phic Cameras\",\"group\":\"Writing\",\"detail\":\"Raymarching SDF CSG\",\"keywords\":[\"Raymarching SDF CSG\",\"webgl2\",\"raymarching\",\"csg\",\"sdf\",\"renderer\",\"library\",\"twist\",\"bend\",\"noise\",\"orthographic\",\"scenic draft 0 11 warps noise environments and orthographic cameras\"]},{\"href\":\"/blog/scenic-draft-0-9-materials-glass-light-and-lenses\",\"title\":\"Scenic Draft 0.9: Materials, Glass, Light and Lenses\",\"group\":\"Writing\",\"detail\":\"Raymarching SDF CSG\",\"keywords\":[\"Raymarching SDF CSG\",\"webgl2\",\"raymarching\",\"csg\",\"sdf\",\"renderer\",\"library\",\"materials\",\"glass\",\"scenic draft 0 9 materials glass light and lenses\"]},{\"href\":\"/blog/scenic-draft-0-5-domain-repetition-new-primitives-and-non-square-canvases\",\"title\":\"Scenic Draft 0.5: Domain Repetition, New Primitives and Non-Square Canvases\",\"group\":\"Writing\",\"detail\":\"Raymarching SDF CSG\",\"keywords\":[\"Raymarching SDF CSG\",\"webgl2\",\"raymarching\",\"csg\",\"sdf\",\"renderer\",\"library\",\"scenic draft 0 5 domain repetition new primitives and non square canvases\"]},{\"href\":\"/blog/scenic-draft-a-no-dependency-webgl2-raymarching-csg-renderer-library\",\"title\":\"Scenic Draft: A No Dependency WebGL2 Raymarching SDF CSG Renderer Library\",\"group\":\"Writing\",\"detail\":\"Raymarching SDF CSG\",\"keywords\":[\"Raymarching SDF CSG\",\"webgl2\",\"raymarching\",\"csg\",\"renderer\",\"library\",\"scenic draft a no dependency webgl2 raymarching csg renderer library\"]},{\"href\":\"/blog/kindle-ready-ebooks-from-markdown\",\"title\":\"Kindle-Ready eBooks from Markdown\",\"group\":\"Writing\",\"detail\":\"Tools\",\"keywords\":[\"Tools\",\"pandoc\",\"markdown\",\"epub\",\"kindle\",\"ebook\",\"kindle ready ebooks from markdown\"]},{\"href\":\"/blog/an-introduction-to-tsl\",\"title\":\"An Introduction to TSL\",\"group\":\"Writing\",\"detail\":\"Creative Code\",\"keywords\":[\"Creative
1Code\",\"an introduction to tsl\"]},{\"href\":\"/blog/a-remarkably-effective-pattern-for-state-management-in-react-with-valtio\",\"title\":\"A Remarkably Effective Pattern for State Management in React with Valtio\",\"group\":\"Writing\",\"detail\":\"React\",\"keywords\":[\"React\",\"valtio\",\"react\",\"state\",\"a remarkably effective pattern for state management in react with valtio\"]},{\"href\":\"/blog/an-introduction-to-replicad-typescript-cad\",\"title\":\"An introduction to CAD in TypeScript with Replicad\",\"group\":\"Writing\",\"detail\":\"Creative Code\",\"keywords\":[\"Creative Code\",\"an introduction to replicad typescript cad\"]},{\"href\":\"/blog/Christmas-2025-blender-geometry-nodes-3d-print\",\"title\":\"Christmas Ornament for 2025, or an introduction to 3D Printing with Blender Geometry Nodes\",\"group\":\"Writing\",\"detail\":\"Creative Code\",\"keywords\":[\"Creative Code\",\"Christmas 2025 blender geometry nodes 3d print\"]},{\"href\":\"/blog/OpenSCAD-programmatic-3D-printing-for-developers\",\"title\":\"OpenSCAD: 3D Printing for Developers\",\"group\":\"Writing\",\"detail\":\"Creative Code\",\"keywords\":[\"Creative
1Code\",\"OpenSCAD programmatic 3D printing for developers\"]},{\"href\":\"/blog/creating-cut-and-folds-or-pop-up-patterns-with-typescript\",\"title\":\"Creating Cut-and-Fold or Pop-Up Patterns with TypeScript\",\"group\":\"Writing\",\"detail\":\"$undefined\",\"keywords\":[\"solandra\",\"svg\",\"solandra-svg\",\"vector graphics\",\"creating cut and folds or pop up patterns with typescript\"]},{\"href\":\"/blog/combining-vector-and-shaders-for-2d-art\",\"title\":\"Combining Vector Graphics and Shaders with Solandra\",\"group\":\"Writing\",\"detail\":\"$undefined\",\"keywords\":[\"solandra\",\"shaders\",\"vector graphics\",\"combining vector and shaders for 2d art\"]},{\"href\":\"/blog/creating-sketches-with-solandra-for-amimetic\",\"title\":\"Creating Sketches with Solandra for the Amimetic Website\",\"group\":\"Writing\",\"detail\":\"$undefined\",\"keywords\":[\"solandra\",\"creative coding\",\"art\",\"sketches\",\"creating sketches with solandra for amimetic\"]},{\"href\":\"/blog/ray-marching-with-swift-and-metal-for-shadertoy-like-graphics\",\"title\":\"Raymarching with Swift and Metal for Shadertoy-like Graphics\",\"group\":\"Writing\",\"detail\":\"Creative Code\",\"keywords\":[\"Creative
1Code\",\"shaders\",\"metal\",\"swift\",\"graphics\",\"generative\",\"creative coding\",\"coding\",\"art\",\"3d\",\"raymarching\",\"ray marching with swift and metal for shadertoy like graphics\"]},{\"href\":\"/blog/no-code-creative-coding-generative-art\",\"title\":\"No Code Creative Coding: A Case Study\",\"group\":\"Writing\",\"detail\":\"Creative Code\",\"keywords\":[\"Creative Code\",\"graphics\",\"generative\",\"creative coding\",\"coding\",\"art\",\"no code\",\"low code\",\"no code creative coding generative art\"]},{\"href\":\"/blog/use-svg-maker-or-creating-svgs-with-react\",\"title\":\"use-svg-maker or Creating SVGs with React: A Tutorial\",\"group\":\"Writing\",\"detail\":\"React\",\"keywords\":[\"React\",\"react\",\"svg\",\"graphics\",\"use svg maker or creating svgs with react\"]},{\"href\":\"/blog/swiftui-for-small-internal-desktop-app-tools\",\"title\":\"SwiftUI for Mini Desktop Apps: A Tutorial\",\"group\":\"Writing\",\"detail\":\"Apps\",\"keywords\":[\"Apps\",\"swift\",\"swiftui\",\"apps\",\"declarative ui\",\"swiftui for small internal desktop app tools\"]},{\"href\":\"/blog/on-consistency\",\"title\":\"On Consistency\",\"group\":\"Writing\",\"detail\":\"Architecture\",\"keywords\":[\"Architecture\",\"consistency\",\"approaches\",\"priorities\",\"importance\",\"dry\",\"on consistency\"]},{\"href\":\"/blog/using-focusstate-and-text-fields-in-swiftui-3\",\"title\":\"@FocusState, TextFields, TextEditor in SwiftUI 3.0\",\"group\":\"Writing\",\"detail\":\"Apps\",\"keywords\":[\"Apps\",\"swift\",\"swiftui\",\"apps\",\"declarative ui\",\"using focusstate and text fields in swiftui 3\"]},{\"href\":\"/blog/swiftui-in-late-2021\",\"title\":\"SwiftUI in late 2021\",\"group\":\"Writing\",\"detail\":\"Apps\",\"keywords\":[\"Apps\",\"swift\",\"swiftui\",\"apps\",\"declarative ui\",\"swiftui in late 2021\"]},{\"href\":\"/blog/flutter-in-late-2021\",\"title\":\"Flutter in Late 2021\",\"group\":\"Writing\",\"detail\":\"Apps\",\"keywords\":[\"Apps\",\"flutter\",\"apps\",\"cross platform\",\"hot reload\",\"react native\",\"react\",\"declarative ui\",\"flutter in late 2021\"]},{\"href\":\"/blog/an-introduction-to-generative-animations-with-remotion-and-solandra\",\"title\":\"Generative Animated Videos with Remotion (and Solandra)\",\"group\":\"Writing\",\"detail\":\"Creative Code\",\"keywords\":[\"Creative
1Code\",\"algorithmic art\",\"drawing\",\"animation\",\"graphics\",\"2d\",\"remotion\",\"an introduction to generative animations with remotion and solandra\"]},{\"href\":\"/blog/flutter-for-algorithmic-art\",\"title\":\"Flutter, an Ideal Framework for Algorithmic Art?\",\"group\":\"Writing\",\"detail\":\"Creative Code\",\"keywords\":[\"Creative Code\",\"flutter\",\"algorithmic art\",\"drawing\",\"animation\",\"graphics\",\"2d\",\"flutter for algorithmic art\"]},{\"href\":\"/blog/react-native-setup-in-2021\",\"title\":\"React Native Setup in Late 2021\",\"group\":\"Writing\",\"detail\":\"React\",\"keywords\":[\"React\",\"react native\",\"react\",\"react navigation\",\"valtio\",\"reanimated\",\"react native setup in 2021\"]},{\"href\":\"/blog/an-introduction-to-react-native-reanimated-2\",\"title\":\"An Introduction to React Native Reanimated 2\",\"group\":\"Writing\",\"detail\":\"React\",\"keywords\":[\"React\",\"react native\",\"animation\",\"reanimated\",\"react\",\"an introduction to react native reanimated 2\"]},{\"href\":\"/blog/valtio-a-great-default-state-management-solution-for-react\",\"title\":\"Valtio: A great state management solution for React\",\"group\":\"Writing\",\"detail\":\"React\",\"keywords\":[\"React\",\"valtio\",\"react\",\"state\",\"valtio a great default state management solution for react\"]},{\"href\":\"/blog/getting-started-with-thermal-printing\",\"title\":\"Getting Started with Thermal Printing\",\"group\":\"Writing\",\"detail\":\"Creative Code\",\"keywords\":[\"Creative
1Code\",\"getting started with thermal printing\"]},{\"href\":\"/blog/getting-started-with-react-native-in-2020\",\"title\":\"Getting Started with React Native in 2020\",\"group\":\"Writing\",\"detail\":\"$undefined\",\"keywords\":[\"getting started with react native in 2020\"]},{\"href\":\"/blog/a-concrete-example-of-why-apples-docs-are-terrible\",\"title\":\"A concrete example of why Apple's documentation is terrible\",\"group\":\"Writing\",\"detail\":\"$undefined\",\"keywords\":[\"a concrete example of why apples docs are terrible\"]},{\"href\":\"/blog/react-ish-ios-apps-a-tutorial\",\"title\":\"React-ish iOS Apps: A Tutorial\",\"group\":\"Writing\",\"detail\":\"$undefined\",\"keywords\":[\"react ish ios apps a tutorial\"]},{\"href\":\"/blog/starting-with-flutter-from-react-native\",\"title\":\"Starting with Flutter (from React Native)\",\"group\":\"Writing\",\"detail\":\"Apps\",\"keywords\":[\"Apps\",\"starting with flutter from react native\"]},{\"href\":\"/blog/getting-started-with-functional-music-programming\",\"title\":\"Getting Started with Functional Music Programming\",\"group\":\"Writing\",\"detail\":\"Functional Programming\",\"keywords\":[\"Functional Programming\",\"getting started with functional music programming\"]},{\"href\":\"/blog/upgrading-to-elm-0-19-in-early-2019\",\"title\":\"Upgrading to Elm 0.19 in early 2019\",\"group\":\"Writing\",\"detail\":\"Functional Programming\",\"keywords\":[\"Functional Programming\",\"upgrading to elm 0 19 in early 2019\"]},{\"href\":\"/blog/OpenJSCAD\",\"title\":\"OpenJSCAD\",\"group\":\"Writing\",\"detail\":\"Creative Code\",\"keywords\":[\"Creative
1Code\",\"OpenJSCAD\"]},{\"href\":\"/blog/Creating-a-watch\",\"title\":\"Creating a Watch\",\"group\":\"Writing\",\"detail\":\"Creative Code\",\"keywords\":[\"Creative Code\",\"Creating a watch\"]},{\"href\":\"/blog/a-few-big-ideas\",\"title\":\"A few big ideas\",\"group\":\"Writing\",\"detail\":\"$undefined\",\"keywords\":[\"ideas\",\"heuristics\",\"a few big ideas\"]},{\"href\":\"/blog/elixir-versus-javascript\",\"title\":\"Elixir Versus JavaScript\",\"group\":\"Writing\",\"detail\":\"$undefined\",\"keywords\":[\"elixir\",\"javascript\",\"programming\",\"functional\",\"fp\",\"elixir versus javascript\"]},{\"href\":\"/blog/better-british-time\",\"title\":\"Better British Time\",\"group\":\"Writing\",\"detail\":\"$undefined\",\"keywords\":[\"timezones\",\"time\",\"brexit\",\"better british time\"]}]}],\"$L17\",\"$L18\"]}]]\n"])</script>
1<script>self.__next_f.push([1,"19:I[90930,[\"/_next/static/chunks/1mea94bxzf98z.js\",\"/_next/static/chunks/2o6yuqk6ct-vf.js\",\"/_next/static/chunks/3myhzjsh1prxr.js\"],\"\"]\n"])</script>
1<script>self.__next_f.push([1,"17:[\"$\",\"main\",null,{\"className\":\"flex-auto\",\"children\":[\"$\",\"$L4\",null,{\"parallelRouterKey\":\"children\",\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L5\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":[[\"$\",\"div\",null,{\"ref\":\"$undefined\",\"className\":\"sm:px-8 flex h-full items-center pt-16 sm:pt-32\",\"children\":[\"$\",\"div\",null,{\"className\":\"mx-auto w-full max-w-7xl lg:px-8\",\"children\":[\"$\",\"div\",null,{\"ref\":\"$undefined\",\"className\":\"relative px-4 sm:px-8 lg:px-12\",\"children\":[\"$\",\"div\",null,{\"className\":\"mx-auto max-w-2xl lg:max-w-5xl\",\"children\":[\"$\",\"div\",null,{\"className\":\"flex flex-col items-center\",\"children\":[[\"$\",\"p\",null,{\"className\":\"text-base font-semibold text-zinc-400 dark:text-zinc-500\",\"children\":\"404\"}],[\"$\",\"h1\",null,{\"className\":\"mt-4 text-4xl font-bold tracking-tight text-rose-800 sm:text-5xl dark:text-rose-100\",\"children\":\"Page not found\"}],[\"$\",\"p\",null,{\"className\":\"mt-4 text-base text-zinc-600 dark:text-zinc-400\",\"children\":\"Sorry, we couldnât find the page youâre looking for.\"}],[\"$\",\"p\",null,{\"className\":\"mt-4 text-base text-zinc-600 dark:text-zinc-400\",\"children\":[\"You may want to try\",\" \",[\"$\",\"a\",null,{\"href\":\"https://archive.amimetic.co.uk\",\"className\":\"font-semibold text-rose-600 hover:text-rose-500\",\"children\":\"the old version of this website\"}],\" \",\"as not everything was included here.\"]}],[\"$\",\"$L19\",null,{\"className\":\"inline-flex items-center gap-2 justify-center rounded-md py-2 px-3 text-sm outline-offset-2 transition active:transition-none bg-zinc-50 font-medium text-zinc-900 hover:bg-zinc-100 active:bg-zinc-100 active:text-zinc-900/60 dark:bg-zinc-800/50 dark:text-zinc-300 dark:hover:bg-zinc-800 dark:hover:text-zinc-50 dark:active:bg-zinc-800/50 dark:active:text-zinc-50/70 mt-4\",\"href\":\"/\",\"children\":\"Go back home\"}]]}]}]}]}]}],[]],\"forbidden\":\"$undefined\",\"unauthorized\":\"$undefined\"}]}]\n"])</script>
1<script>self.__next_f.push([1,"18:[\"$\",\"footer\",null,{\"className\":\"mt-32 flex-none\",\"children\":[\"$\",\"div\",null,{\"ref\":\"$undefined\",\"className\":\"sm:px-8\",\"children\":[\"$\",\"div\",null,{\"className\":\"mx-auto w-full max-w-7xl lg:px-8\",\"children\":[\"$\",\"div\",null,{\"className\":\"border-t border-zinc-100 pb-16 pt-10 dark:border-zinc-700/40\",\"children\":[\"$\",\"div\",null,{\"ref\":\"$undefined\",\"className\":\"relative px-4 sm:px-8 lg:px-12\",\"children\":[\"$\",\"div\",null,{\"className\":\"mx-auto max-w-2xl lg:max-w-5xl\",\"children\":[\"$\",\"div\",null,{\"className\":\"flex flex-col items-center justify-between gap-6 sm:flex-row\",\"children\":[[\"$\",\"div\",null,{\"className\":\"flex flex-wrap justify-center gap-x-6 gap-y-1 text-sm font-medium text-zinc-800 dark:text-zinc-200\",\"children\":[[\"$\",\"$L19\",null,{\"href\":\"/about\",\"className\":\"transition hover:text-sky-500 dark:hover:text-sky-400\",\"children\":\"About\"}],[\"$\",\"$L19\",null,{\"href\":\"/blog\",\"className\":\"transition hover:text-sky-500 dark:hover:text-sky-400\",\"children\":\"Writing\"}],[\"$\",\"$L19\",null,{\"href\":\"/projects\",\"className\":\"transition hover:text-sky-500 dark:hover:text-sky-400\",\"children\":\"Projects\"}]]}],[\"$\",\"div\",null,{\"className\":\"flex flex-col items-center gap-1 sm:items-end\",\"children\":[[\"$\",\"p\",null,{\"className\":\"text-sm text-zinc-400 dark:text-zinc-500\",\"children\":[\"© \",2026,\" James Porter\"]}],[\"$\",\"p\",null,{\"className\":\"max-w-sm text-center text-xs text-zinc-400 sm:text-right dark:text-zinc-500\",\"children\":\"By training your LLM or AI service on this website you agree to pay 20% of gross worldwide revenue to James Porter in perpetuity.\"}]]}]]}]}]}]}]}]}]}]\n"])</script>
1</body></html>
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.