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/20ghcu2c4o0h-.js" async=""></script>
1<title>About - James Porter</title><meta name="description" content="James Porter - Software - Data - Creative Coding"/><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 text-sky-500 dark:text-sky-400" href="/about">About<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><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 hover:text-sky-500 dark:hover:text-sky-400" href="/projects">Projects</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"><div class="grid grid-cols-1 gap-y-16 lg:grid-cols-2 lg:grid-rows-[auto_1fr] lg:gap-y-12"><div class="lg:pl-20"><div class="max-w-xs px-2.5 lg:max-w-none"><canvas width="480" height="480" style="width:100%;height:100%"></canvas></div></div><div class="lg:order-first lg:row-span-2"><h1 class="text-4xl font-bold tracking-tight text-zinc-800 sm:text-5xl dark:text-zinc-100">James Porter</h1><div class="mt-6 space-y-7 text-base text-zinc-600 dark:text-zinc-400"><p>This website brings together some of my writing and projects.</p></div></div><div class="lg:pl-20"><ul role="list" class="flex flex-col gap-4"><li class="flex"><a class="group flex text-sm font-medium text-zinc-800 transition hover:text-sky-500 dark:text-zinc-200 dark:hover:text-sky-500" href="https://github.com/jamesporter"><svg viewBox="0 0 24 24" aria-hidden="true" class="h-6 w-6 flex-none fill-zinc-500 transition group-hover:fill-sky-500"><path fill-rule="evenodd" clip-rule="evenodd" d="M12 2C6.475 2 2 6.588 2 12.253c0 4.537 2.862 8.369 6.838 9.727.5.09.687-.218.687-.487 0-.243-.013-1.05-.013-1.91C7 20.059 6.35 18.957 6.15 18.38c-.113-.295-.6-1.205-1.025-1.448-.35-.192-.85-.667-.013-.68.788-.012 1.35.744 1.538 1.051.9 1.551 2.338 1.116 2.912.846.088-.666.35-1.115.638-1.371-2.225-.256-4.55-1.14-4.55-5.062 0-1.115.387-2.038 1.025-2.756-.1-.256-.45-1.307.1-2.717 0 0 .837-.269 2.75 1.051.8-.23 1.65-.346 2.5-.346.85 0 1.7.115 2.5.346 1.912-1.333 2.75-1.05 2.75-1.05.55 1.409.2 2.46.1 2.716.637.718 1.025 1.628 1.025 2.756 0 3.934-2.337 4.806-4.562 5.062.362.32.675.936.675 1.897 0 1.371-.013 2.473-.013 2.82 0 .268.188.589.688.486a10.039 10.039 0 0 0 4.932-3.74A10.447 10.447 0 0 0 22 12.253C22 6.588 17.525 2 12 2Z"></path></svg><span class="ml-4">Follow on GitHub</span></a></li><li class="flex"><a class="group flex text-sm font-medium text-zinc-800 transition hover:text-sky-500 dark:text-zinc-200 dark:hover:text-sky-500" href="https://twitter.com/complexview"><svg viewBox="0 0 24 24" aria-hidden="true" class="h-6 w-6 flex-none fill-zinc-500 transition group-hover:fill-sky-500"><path d="M13.3174 10.7749L19.1457 4H17.7646L12.7039 9.88256L8.66193 4H4L10.1122 12.8955L4 20H5.38119L10.7254 13.7878L14.994 20H19.656L13.3171 10.7749H13.3174ZM11.4257 12.9738L10.8064 12.0881L5.87886 5.03974H8.00029L11.9769 10.728L12.5962 11.6137L17.7652 19.0075H15.6438L11.4257 12.9742V12.9738Z"></path></svg><span class="ml-4">Follow on X</span></a></li><li class="flex"><a class="group flex text-sm font-medium text-zinc-800 transition hover:text-sky-500 dark:text-zinc-200 dark:hover:text-sky-500" href="https://www.linkedin.com/in/james-porter-77932b11/"><svg viewBox="0 0 24 24" aria-hidden="true" class="h-6 w-6 flex-none fill-zinc-500 transition group-hover:fill-sky-500"><path d="M18.335 18.339H15.67v-4.177c0-.996-.02-2.278-1.39-2.278-1.389 0-1.601 1.084-1.601 2.205v4.25h-2.666V9.75h2.56v1.17h.035c.358-.674 1.228-1.387 2.528-1.387 2.7 0 3.2 1.778 3.2 4.091v4.715zM7.003 8.575a1.546 1.546 0 01-1.548-1.549 1.548 1.548 0 111.547 1.549zm1.336 9.764H5.666V9.75H8.34v8.589zM19.67 3H4.329C3.593 3 3 3.58 3 4.297v15.406C3 20.42 3.594 21 4.328 21h15.338C20.4 21 21 20.42 21 19.703V4.297C21 3.58 20.4 3 19.666 3h.003z"></path></svg><span class="ml-4">Follow on LinkedIn</span></a></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[1524,[\"/_next/static/chunks/1mea94bxzf98z.js\",\"/_next/static/chunks/2o6yuqk6ct-vf.js\",\"/_next/static/chunks/3myhzjsh1prxr.js\",\"/_next/static/chunks/20ghcu2c4o0h-.js\"],\"IndexPageCard\"]\n7:I[90930,[\"/_next/static/chunks/1mea94bxzf98z.js\",\"/_next/static/chunks/2o6yuqk6ct-vf.js\",\"/_next/static/chunks/3myhzjsh1prxr.js\",\"/_next/static/chunks/20ghcu2c4o0h-.js\"],\"\"]\ne: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\":[\"\",\"about\"],\"q\":\"\",\"i\":false,\"f\":[[[\"\",{\"children\":[\"about\",{\"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\":[\"$\",\"div\",null,{\"className\":\"grid grid-cols-1 gap-y-16 lg:grid-cols-2 lg:grid-rows-[auto_1fr] lg:gap-y-12\",\"children\":[[\"$\",\"div\",null,{\"className\":\"lg:pl-20\",\"children\":[\"$\",\"div\",null,{\"className\":\"max-w-xs px-2.5 lg:max-w-none\",\"children\":[\"$\",\"$L6\",null,{\"imageIndex\":0}]}]}],[\"$\",\"div\",null,{\"className\":\"lg:order-first lg:row-span-2\",\"children\":[[\"$\",\"h1\",null,{\"className\":\"text-4xl font-bold tracking-tight text-zinc-800 sm:text-5xl dark:text-zinc-100\",\"children\":\"James Porter\"}],[\"$\",\"div\",null,{\"className\":\"mt-6 space-y-7 text-base text-zinc-600 dark:text-zinc-400\",\"children\":[\"$\",\"p\",null,{\"children\":\"This website brings together some of my writing and projects.\"}]}]]}],[\"$\",\"div\",null,{\"className\":\"lg:pl-20\",\"children\":[\"$\",\"ul\",null,{\"role\":\"list\",\"className\":\"flex flex-col gap-4\",\"children\":[[\"$\",\"li\",null,{\"className\":\"flex\",\"children\":[\"$\",\"$L7\",null,{\"href\":\"https://github.com/jamesporter\",\"className\":\"group flex text-sm font-medium text-zinc-800 transition hover:text-sky-500 dark:text-zinc-200 dark:hover:text-sky-500\",\"children\":[[\"$\",\"svg\",null,{\"viewBox\":\"0 0 24 24\",\"aria-hidden\":\"true\",\"className\":\"h-6 w-6 flex-none fill-zinc-500 transition group-hover:fill-sky-500\",\"children\":[\"$\",\"path\",null,{\"fillRule\":\"evenodd\",\"clipRule\":\"evenodd\",\"d\":\"M12 2C6.475 2 2 6.588 2 12.253c0 4.537 2.862 8.369 6.838 9.727.5.09.687-.218.687-.487 0-.243-.013-1.05-.013-1.91C7 20.059 6.35 18.957 6.15 18.38c-.113-.295-.6-1.205-1.025-1.448-.35-.192-.85-.667-.013-.68.788-.012 1.35.744 1.538 1.051.9 1.551 2.338 1.116 2.912.846.088-.666.35-1.115.638-1.371-2.225-.256-4.55-1.14-4.55-5.062 0-1.115.387-2.038 1.025-2.756-.1-.256-.45-1.307.1-2.717 0 0 .837-.269 2.75 1.051.8-.23 1.65-.346 2.5-.346.85 0 1.7.115 2.5.346 1.912-1.333 2.75-1.05 2.75-1.05.55 1.409.2 2.46.1 2.716.637.718 1.025 1.628 1.025 2.756 0 3.934-2.337 4.806-4.562 5.062.362.32.675.936.675 1.897 0 1.371-.013 2.473-.013 2.82 0 .268.188.589.688.486a10.039 10.039 0 0 0 4.932-3.74A10.447 10.447 0 0 0 22 12.253C22 6.588 17.525 2 12 2Z\"}]}],[\"$\",\"span\",null,{\"className\":\"ml-4\",\"children\":\"Follow on GitHub\"}]]}]}],[\"$\",\"li\",null,{\"className\":\"flex\",\"children\":[\"$\",\"$L7\",null,{\"href\":\"https://twitter.com/complexview\",\"className\":\"group flex text-sm font-medium text-zinc-800 transition hover:text-sky-500 dark:text-zinc-200 dark:hover:text-sky-500\",\"children\":[[\"$\",\"svg\",null,{\"viewBox\":\"0 0 24 24\",\"aria-hidden\":\"true\",\"className\":\"h-6 w-6 flex-none fill-zinc-500 transition group-hover:fill-sky-500\",\"children\":[\"$\",\"path\",null,{\"d\":\"M13.3174 10.7749L19.1457 4H17.7646L12.7039 9.88256L8.66193 4H4L10.1122 12.8955L4 20H5.38119L10.7254 13.7878L14.994 20H19.656L13.3171 10.7749H13.3174ZM11.4257 12.9738L10.8064 12.0881L5.87886 5.03974H8.00029L11.9769 10.728L12.5962 11.6137L17.7652 19.0075H15.6438L11.4257 12.9742V12.9738Z\"}]}],\"$L8\"]}]}],\"$L9\"]}]}]]}]}]}]}]}],[\"$La\"],\"$Lb\"]}],{}
1,null,false,null]},null,false,\"$@c\"]},null,false,null],\"$Ld\",false]],\"m\":\"$undefined\",\"G\":[\"$e\",[\"$Lf\"]],\"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,"10:I[1145,[\"/_next/static/chunks/1mea94bxzf98z.js\",\"/_next/static/chunks/2o6yuqk6ct-vf.js\",\"/_next/static/chunks/3myhzjsh1prxr.js\"],\"OutletBoundary\"]\n11:\"$Sreact.suspense\"\n14:I[1145,[\"/_next/static/chunks/1mea94bxzf98z.js\",\"/_next/static/chunks/2o6yuqk6ct-vf.js\",\"/_next/static/chunks/3myhzjsh1prxr.js\"],\"ViewportBoundary\"]\n16:I[1145,[\"/_next/static/chunks/1mea94bxzf98z.js\",\"/_next/static/chunks/2o6yuqk6ct-vf.js\",\"/_next/static/chunks/3myhzjsh1prxr.js\"],\"MetadataBoundary\"]\n8:[\"$\",\"span\",null,{\"className\":\"ml-4\",\"children\":\"Follow on X\"}]\n9:[\"$\",\"li\",null,{\"className\":\"flex\",\"children\":[\"$\",\"$L7\",null,{\"href\":\"https://www.linkedin.com/in/james-porter-77932b11/\",\"className\":\"group flex text-sm font-medium text-zinc-800 transition hover:text-sky-500 dark:text-zinc-200 dark:hover:text-sky-500\",\"children\":[[\"$\",\"svg\",null,{\"viewBox\":\"0 0 24 24\",\"aria-hidden\":\"true\",\"className\":\"h-6 w-6 flex-none fill-zinc-500 transition group-hover:fill-sky-500\",\"children\":[\"$\",\"path\",null,{\"d\":\"M18.335 18.339H15.67v-4.177c0-.996-.02-2.278-1.39-2.278-1.389 0-1.601 1.084-1.601 2.205v4.25h-2.666V9.75h2.56v1.17h.035c.358-.674 1.228-1.387 2.528-1.387 2.7 0 3.2 1.778 3.2 4.091v4.715zM7.003 8.575a1.546 1.546 0 01-1.548-1.549 1.548 1.548 0 111.547 1.549zm1.336 9.764H5.666V9.75H8.34v8.589zM19.67 3H4.329C3.593 3 3 3.58 3 4.297v15.406C3 20.42 3.594 21 4.328 21h15.338C20.4 21 21 20.42 21 19.703V4.297C21 3.58 20.4 3 19.666 3h.003z\"}]}],[\"$\",\"span\",null,{\"className\":\"ml-4\",\"children\":\"Follow on LinkedIn\"}]]}]}]\na:[\"$\",\"script\",\"script-0\",{\"src\":\"/_next/static/chunks/20ghcu2c4o0h-.js\",\"async\":true,\"nonce\":\"$undefined\"}]\nb:[\"$\",\"$L10\",null,{\"children\":[\"$\",\"$11\",null,{\"name\":\"Next.MetadataOutlet\",\"children\":\"$@12\"}]}]\n13:[]\nc:\"$W13\"\nd:[\"$\",\"$1\",\"h\",{\"children\":[null,[\"$\",\"$L14\",null,{\"children\":\"$L15\"}],[\"$\",\"div\",null,{\"hidden\":true,\"children\":[\"$\",\"$L16\",null,{\"children\":[\"$\",\"$11\",null,{\"name\":\"Next.Metadata\",\"children\":\"$L17\"}]}]}],null]}]\nf:[\"$\",\"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,"15:[[\"$\",\"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,"18:I[61573,[\"/_next/static/chunks/1mea94bxzf98z.js\",\"/_next/static/chunks/2o6yuqk6ct-vf.js\",\"/_next/static/chunks/3myhzjsh1prxr.js\"],\"IconMark\"]\n12:null\n17:[[\"$\",\"title\",\"0\",{\"children\":\"About - James Porter\"}],[\"$\",\"meta\",\"1\",{\"name\":\"description\",\"content\":\"James Porter - Software - Data - Creative Coding\"}],[\"$\",\"link\",\"2\",{\"rel\":\"icon\",\"href\":\"/icon.png?icon.30-pyszslje08.png\",\"sizes\":\"512x512\",\"type\":\"image/png\"}],[\"$\",\"$L18\",\"3\",{}]]\n"])</script>
1<script>self.__next_f.push([1,"19: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\":[[\"$\",\"$L19\",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\"]}]}],\"$L1a\",\"$L1b\"]}]]\n"])</script>
1<script>self.__next_f.push([1,"1a:[\"$\",\"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.\"]}],[\"$\",\"$L7\",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,"1b:[\"$\",\"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\":[[\"$\",\"$L7\",null,{\"href\":\"/about\",\"className\":\"transition hover:text-sky-500 dark:hover:text-sky-400\",\"children\":\"About\"}],[\"$\",\"$L7\",null,{\"href\":\"/blog\",\"className\":\"transition hover:text-sky-500 dark:hover:text-sky-400\",\"children\":\"Writing\"}],[\"$\",\"$L7\",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.