-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.html
308 lines (284 loc) · 27.6 KB
/
index.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
<!DOCTYPE html>
<html lang="en" class="motion-safe:scroll-smooth 2xl:text-[20px]">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Ian Wootten — Software Developer, Cardiff</title>
<meta name="robots" content="index,follow" />
<meta name="description" content="Ian Wootten is a Software Developer in Cardiff, UK. He helps companies solve complex problems with simple software. He uses tools like Python, Terraform and Serverless to deliver solutions and iterate quickly." />
<meta name="twitter:card" content="summary_large_image" />
<meta property="og:title" content="Ian Wootten — Software Developer, Cardiff" />
<meta property="og:description" content="Ian Wootten is a Software Developer in Cardiff, UK. He helps companies solve complex problems with simple software. He uses tools like Python, Terraform and Serverless to deliver solutions and iterate quickly." />
<meta property="og:url" content="https://www.ianwootten.co.uk/" />
<meta property="og:type" content="website" />
<meta property="og:image" content="https://www.ianwootten.co.uk/assets/default.d89fbbc5_1WbbAJ.jpg" />
<meta property="og:image:alt" content="Ian Wootten — Software Developer, Cardiff" />
<link rel="canonical" href="https://www.ianwootten.co.uk/" />
<!-- Or Google Fonts -->
<meta name="google-site-verification" content="orcPxI47GSa-cRvY11tUe6iGg2IO_RPvnA1q95iEM3M">
<script defer data-domain="ianwootten.co.uk" src="https://analytics.niftydigits.com/js/plausible.js"></script>
<link rel="shortcut icon" href="/favicon.ico">
<link rel="icon" type="image/svg+xml" href="/favicon.svg">
<link rel="mask-icon" href="/favicon.svg" color="#8D46E7">
<link rel="stylesheet" href="/assets/_...page_.0987525b.css" />
<link rel="stylesheet" href="/assets/_slug_.9a3e7945.css" />
<link rel="stylesheet" href="/assets/index.a49322ed.css" /><script type="module">class c extends HTMLElement{connectedCallback(){this.videoId=this.getAttribute("videoid");let e=this.querySelector(".lty-playbtn");if(this.playLabel=e&&e.textContent.trim()||this.getAttribute("playlabel")||"Play",this.style.backgroundImage||(this.posterUrl=`https://i.ytimg.com/vi/${this.videoId}/hqdefault.jpg`,c.addPrefetch("preload",this.posterUrl,"image"),this.style.backgroundImage=`url("${this.posterUrl}")`),e||(e=document.createElement("button"),e.type="button",e.classList.add("lty-playbtn"),this.append(e)),!e.textContent){const t=document.createElement("span");t.className="lyt-visually-hidden",t.textContent=this.playLabel,e.append(t)}this.addEventListener("pointerover",c.warmConnections,{once:!0}),this.addEventListener("click",t=>this.addIframe())}static addPrefetch(e,t,o){const n=document.createElement("link");n.rel=e,n.href=t,o&&(n.as=o),document.head.append(n)}static warmConnections(){c.preconnected||(c.addPrefetch("preconnect","https://www.youtube-nocookie.com"),c.addPrefetch("preconnect","https://www.google.com"),c.addPrefetch("preconnect","https://googleads.g.doubleclick.net"),c.addPrefetch("preconnect","https://static.doubleclick.net"),c.preconnected=!0)}addIframe(){const e=new URLSearchParams(this.getAttribute("params")||[]);e.append("autoplay","1");const t=document.createElement("iframe");t.width=560,t.height=315,t.title=this.playLabel,t.allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture",t.allowFullscreen=!0,t.src=`https://www.youtube-nocookie.com/embed/${encodeURIComponent(this.videoId)}?${e.toString()}`,this.append(t),this.classList.add("lyt-activated"),this.querySelector("iframe").focus()}}customElements.define("lite-youtube",c);class a extends HTMLElement{videoId;static preconnected=!1;connectedCallback(){this.videoId=encodeURIComponent(this.dataset.id),this.addEventListener("pointerover",a.warmConnections,{once:!0}),this.addEventListener("click",e=>this.addIframe(e))}static addPrefetch(e,t){const o=document.createElement("link");o.rel=e,o.href=t,document.head.append(o)}static warmConnections(){a.preconnected||(a.addPrefetch("preconnect","https://player.vimeo.com"),a.addPrefetch("preconnect","https://i.vimeocdn.com"),a.addPrefetch("preconnect","https://f.vimeocdn.com"),a.addPrefetch("preconnect","https://fresnel.vimeocdn.com"),a.preconnected=!0)}addIframe(e){if(this.classList.contains("ltv-activated"))return;e.preventDefault(),this.classList.add("ltv-activated");const t=encodeURIComponent(this.dataset.t||"0m"),o=new URLSearchParams(this.dataset.params||[]),n=document.createElement("iframe");n.width="640",n.height="360",n.allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture",n.allowFullscreen=!0,n.src=`https://player.vimeo.com/video/${this.videoId}?${o.toString()}#t=${t}`,this.append(n)}}customElements.define("lite-vimeo",a);
</script>
<script>!(function(w,p,f,c){c=w[p]=Object.assign(w[p]||{},{"lib":"/~partytown/","debug":false});c[f]=(c[f]||[]).concat(["dataLayer.push"])})(window,'partytown','forward');/* Partytown 0.7.3 - MIT builder.io */
!function(t,e,n,i,r,o,a,d,s,c,p,l){function u(){l||(l=1,"/"==(a=(o.lib||"/~partytown/")+(o.debug?"debug/":""))[0]&&(s=e.querySelectorAll('script[type="text/partytown"]'),i!=t?i.dispatchEvent(new CustomEvent("pt1",{detail:t})):(d=setTimeout(w,1e4),e.addEventListener("pt0",f),r?h(1):n.serviceWorker?n.serviceWorker.register(a+(o.swPath||"partytown-sw.js"),{scope:a}).then((function(t){t.active?h():t.installing&&t.installing.addEventListener("statechange",(function(t){"activated"==t.target.state&&h()}))}),console.error):w())))}function h(t){c=e.createElement(t?"script":"iframe"),t||(c.setAttribute("style","display:block;width:0;height:0;border:0;visibility:hidden"),c.setAttribute("aria-hidden",!0)),c.src=a+"partytown-"+(t?"atomics.js?v=0.7.3":"sandbox-sw.html?"+Date.now()),e.body.appendChild(c)}function w(t,n){for(f(),t=0;t<s.length;t++)(n=e.createElement("script")).innerHTML=s[t].innerHTML,e.head.appendChild(n);c&&c.parentNode.removeChild(c)}function f(){clearTimeout(d)}o=t.partytown||{},i==t&&(o.forward||[]).map((function(e){p=t,e.split(".").map((function(e,n,i){p=p[i[n]]=n+1<i.length?"push"==i[n+1]?[]:p[i[n]]||{}:function(){(t._ptf=t._ptf||[]).push(i,arguments)}}))})),"complete"==e.readyState?u():(t.addEventListener("DOMContentLoaded",u),t.addEventListener("load",u))}(window,document,navigator,top,window.crossOriginIsolated);</script></head>
<body class="antialiased text-gray-900 dark:text-slate-300 tracking-tight bg-white dark:bg-slate-900">
<header class="sticky top-0 z-40 flex-none mx-auto w-full bg-white md:bg-white/90 dark:bg-slate-900 dark:md:bg-slate-900/90 md:backdrop-blur-sm border-b dark:border-b-0">
<div class="py-3 px-3 mx-auto w-full md:flex md:justify-between max-w-6xl md:px-4">
<div class="flex justify-between">
<a class="flex items-center" href="/">
<span class="self-center ml-2 text-2xl font-extrabold text-gray-900 whitespace-nowrap dark:text-white">
💻 Ian Wootten</span>
</a>
<div class="flex items-center md:hidden">
<button type="button" class="text-gray-500 dark:text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-700 focus:outline-none focus:ring-4 focus:ring-gray-200 dark:focus:ring-gray-700 rounded-lg text-sm p-2.5 inline-flex items-center" aria-label="Toggle between Dark and Light mode" data-aw-toggle-color-scheme>
<svg viewBox="0 0 24 24" class="w-6 h-6" astro-icon="tabler:sun"><g fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" class="icon-tabler"><circle cx="12" cy="12" r="4"/><path d="M3 12h1m8-9v1m8 8h1m-9 8v1M5.6 5.6l.7.7m12.1-.7-.7.7m0 11.4.7.7m-12.1-.7-.7.7"/></g></svg>
</button>
<button type="button" class="ml-1.5 text-gray-500 dark:text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-800 focus:outline-none focus:ring-4 focus:ring-gray-200 dark:focus:ring-gray-700 rounded-lg text-sm p-2.5 inline-flex items-center transition" aria-label="Toggle Menu" data-aw-toggle-menu>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" preserveAspectRatio="xMidYMid meet" viewBox="0 0 24 24" class="w-6 h-6" astro-icon="tabler:menu"><g class="icon-tabler" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M4 8h16"/><path d="M4 16h16"/></g></svg>
</button>
</div>
</div>
<nav class="items-center w-full md:w-auto hidden md:flex text-gray-600 dark:text-slate-200 h-screen md:h-auto" aria-label="Main navigation" id="menu">
<ul class="flex flex-col pt-8 md:pt-0 md:flex-row md:self-center w-full md:w-auto collapsed text-xl md:text-base">
<li>
<a class="font-medium hover:text-gray-900 dark:hover:text-white px-4 py-3 flex items-center transition duration-150 ease-in-out" href="/blog/">Blog</a>
</li>
<li>
<a class="font-medium hover:text-gray-900 dark:hover:text-white px-4 py-3 flex items-center transition duration-150 ease-in-out" href="/about/">About</a>
</li>
<li>
<a class="font-medium hover:text-gray-900 dark:hover:text-white px-4 py-3 flex items-center transition duration-150 ease-in-out" href="/work-with-me/">Work With Me</a>
</li>
<li>
<a class="font-medium hover:text-gray-900 dark:hover:text-white px-4 py-3 flex items-center transition duration-150 ease-in-out" href="https://niftydigits.gumroad.com/">Products
</a>
</li>
<li>
<a class="font-medium hover:text-gray-900 dark:hover:text-white px-4 py-3 flex items-center transition duration-150 ease-in-out" href="https://newsletter.ianwootten.co.uk">Newsletter
</a>
</li>
<li class="md:hidden">
<a class="font-bold hover:text-gray-900 dark:hover:text-white px-4 py-3 flex items-center transition duration-150 ease-in-out" href="https://www.youtube.com/IanWootten?sub_confirmation=1">YouTube
</a>
</li>
<li class="md:hidden">
<a class="font-bold hover:text-gray-900 dark:hover:text-white px-4 py-3 flex items-center transition duration-150 ease-in-out" href="https://github.com/iwootten">Github
</a>
</li>
</ul>
<div class="md:self-center flex items-center mb-4 md:mb-0 ml-2">
<div class="hidden items-center md:flex">
<button type="button" class="text-gray-500 dark:text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-700 focus:outline-none focus:ring-4 focus:ring-gray-200 dark:focus:ring-gray-700 rounded-lg text-sm p-2.5 inline-flex items-center" aria-label="Toggle between Dark and Light mode" data-aw-toggle-color-scheme>
<svg viewBox="0 0 24 24" class="w-5 h-5" astro-icon="tabler:sun"><g fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" class="icon-tabler"><circle cx="12" cy="12" r="4"/><path d="M3 12h1m8-9v1m8 8h1m-9 8v1M5.6 5.6l.7.7m12.1-.7-.7.7m0 11.4.7.7m-12.1-.7-.7.7"/></g></svg>
</button>
<a href="https://www.youtube.com/IanWootten?sub_confirmation=1" class="inline-block text-gray-500 dark:text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-700 focus:outline-none focus:ring-4 focus:ring-gray-200 dark:focus:ring-gray-700 rounded-lg text-sm p-2.5" aria-label="Ian's YouTube Channel">
<svg viewBox="0 0 24 24" class="w-5 h-5" astro-icon="tabler:brand-youtube"><g fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" class="icon-tabler"><rect width="18" height="14" x="3" y="5" rx="4"/><path d="m10 9 5 3-5 3z"/></g></svg>
</a>
<a href="https://github.com/iwootten" class="inline-block text-gray-500 dark:text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-700 focus:outline-none focus:ring-4 focus:ring-gray-200 dark:focus:ring-gray-700 rounded-lg text-sm p-2.5" aria-label="Ian's Github">
<svg viewBox="0 0 24 24" class="w-5 h-5" astro-icon="tabler:brand-github"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 19c-4.3 1.4-4.3-2.5-6-3m12 5v-3.5c0-1 .1-1.4-.5-2 2.8-.3 5.5-1.4 5.5-6a4.6 4.6 0 0 0-1.3-3.2 4.2 4.2 0 0 0-.1-3.2s-1.1-.3-3.5 1.3a12.3 12.3 0 0 0-6.2 0C6.5 2.8 5.4 3.1 5.4 3.1a4.2 4.2 0 0 0-.1 3.2A4.6 4.6 0 0 0 4 9.5c0 4.6 2.7 5.7 5.5 6-.6.6-.6 1.2-.5 2V21"/></svg>
</a>
<a class="text-gray-500 dark:text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-700 focus:outline-none focus:ring-4 focus:ring-gray-200 dark:focus:ring-gray-700 rounded-lg text-sm p-2.5 inline-flex items-center" aria-label="RSS Feed" href="/rss.xml">
<svg viewBox="0 0 24 24" class="w-5 h-5" astro-icon="tabler:rss"><g fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" class="icon-tabler"><circle cx="5" cy="19" r="1"/><path d="M4 4a16 16 0 0 1 16 16M4 11a9 9 0 0 1 9 9"/></g></svg>
</a>
</div>
</div>
</nav>
</div>
</header><main>
<section>
<div class="max-w-6xl mx-auto px-4 sm:px-6">
<div class="py-12">
<div class="text-center pb-10">
<h1 class="text-5xl md:text-[3.50rem] font-bold leading-tighter tracking-tighter mb-4 font-heading">
<span class="bg-clip-text text-transparent bg-gradient-to-r from-primary-500 to-secondary-500 sm:whitespace-nowrap">Howdy!</span>
</h1>
<div class="max-w-3xl mx-auto">
<p class="text-xl text-gray-600 dark:text-slate-400">
I’m Ian. An independent software engineer who specialises in Python. Here, I share videos and write articles on my latest projects.
</p>
<picture>
<source type="image/avif" srcset="/assets/headshot.cdba7956_7wOOn.avif 256w"><source type="image/webp" srcset="/assets/headshot.cdba7956_PRDM9.webp 256w"><source type="image/jpeg" srcset="/assets/headshot.cdba7956_Z18d5O4.jpg 256w">
<img width="256" height="255" src="/assets/headshot.cdba7956_Z2tdjCG.jpg" loading="lazy" decoding="async" alt="What I look like" class="h-32 w-32 mt-5 rounded-full mx-auto">
</picture>
</div>
</div>
</div>
</div>
</section><section class="px-4 py-16 mx-auto max-w-6xl lg:py-20">
<div class="flex flex-col mb-6 lg:justify-between lg:flex-row md:mb-8">
<h2 class="max-w-lg mb-2 text-3xl font-bold tracking-tight sm:text-4xl sm:leading-none lg:mb-5 group font-heading">
<span class="inline-block mb-1 sm:mb-4">Popular Articles</span>
</h2>
</div>
<div class="grid gap-6 row-gap-5 md:grid-cols-2 lg:grid-cols-4 -mb-6">
<article class="mb-6 transition">
<a href="/2023/04/25/self-hosting-generative-open-graph-art-on-the-edge-with-supabase/" class="hover:text-primary-600 underline underline-offset-4 decoration-1 decoration-dotted transition ease-in duration-200">
<picture>
<source type="image/avif" srcset="/assets/main.abf9a62f_3m9Er.avif 400w,/assets/main.abf9a62f_1JLFQG.avif 900w" sizes="(max-width: 900px) 400px, 900px"><source type="image/webp" srcset="/assets/main.abf9a62f_LGXCd.webp 400w,/assets/main.abf9a62f_2t7uOs.webp 900w" sizes="(max-width: 900px) 400px, 900px"><source type="image/png" srcset="/assets/main.abf9a62f_107UPJ.png 400w,/assets/main.abf9a62f_eqsTS.png 900w" sizes="(max-width: 900px) 400px, 900px">
<img width="900" height="506" src="/assets/main.abf9a62f_Z14aFR8.png" loading="lazy" decoding="async" alt="Self Hosting Generative Open Graph Art on the Edge with Supabase" class="object-cover w-full h-64 mb-6 rounded shadow-lg bg-gray-400 dark:bg-slate-700">
</picture>
</a>
<h3 class="mb-2 text-xl font-bold leading-snug sm:text-2xl font-heading">
<a href="/2023/04/25/self-hosting-generative-open-graph-art-on-the-edge-with-supabase/" class="hover:text-primary-600 underline underline-offset-4 decoration-1 decoration-dotted transition ease-in duration-200">
Self Hosting Generative Open Graph Art on the Edge with Supabase
</a>
</h3>
<p class="text-gray-700 dark:text-gray-400">I show you how you can make unique, randomised open graph images using generative art and then self-host them using Supabase and Fly.io</p>
</article><article class="mb-6 transition">
<a href="/2022/10/24/coding-on-the-steam-deck/" class="hover:text-primary-600 underline underline-offset-4 decoration-1 decoration-dotted transition ease-in duration-200">
<picture>
<source type="image/avif" srcset="/assets/edgar-almeida-steamdeck.6046709e_Zwn6dT.avif 400w,/assets/edgar-almeida-steamdeck.6046709e_1a2pXl.avif 900w" sizes="(max-width: 900px) 400px, 900px"><source type="image/webp" srcset="/assets/edgar-almeida-steamdeck.6046709e_bWHIR.webp 400w,/assets/edgar-almeida-steamdeck.6046709e_1SneV7.webp 900w" sizes="(max-width: 900px) 400px, 900px"><source type="image/jpeg" srcset="/assets/edgar-almeida-steamdeck.6046709e_ZashKp.jpg 400w,/assets/edgar-almeida-steamdeck.6046709e_ZV9JGg.jpg 900w" sizes="(max-width: 900px) 400px, 900px">
<img width="900" height="506" src="/assets/edgar-almeida-steamdeck.6046709e_Zbt6aL.jpg" loading="lazy" decoding="async" alt="Coding on the Steam Deck" class="object-cover w-full h-64 mb-6 rounded shadow-lg bg-gray-400 dark:bg-slate-700">
</picture>
</a>
<h3 class="mb-2 text-xl font-bold leading-snug sm:text-2xl font-heading">
<a href="/2022/10/24/coding-on-the-steam-deck/" class="hover:text-primary-600 underline underline-offset-4 decoration-1 decoration-dotted transition ease-in duration-200">
Coding on the Steam Deck
</a>
</h3>
<p class="text-gray-700 dark:text-gray-400">I got the Valve Steam Deck last month and have instantly become obsessed with it. I wanted to know if I could use it as a linux dev machine, knowing that it was essentially a full blown PC under the hood. </p>
</article><article class="mb-6 transition">
<a href="/2022/08/25/developing-on-the-framework-laptop/" class="hover:text-primary-600 underline underline-offset-4 decoration-1 decoration-dotted transition ease-in duration-200">
<picture>
<source type="image/avif" srcset="/assets/keyboard.c98d0109_Z2o0U4e.avif 400w,/assets/keyboard.c98d0109_ZGAnQY.avif 900w" sizes="(max-width: 900px) 400px, 900px"><source type="image/webp" srcset="/assets/keyboard.c98d0109_Z1EF66s.webp 400w,/assets/keyboard.c98d0109_1Jq5M.webp 900w" sizes="(max-width: 900px) 400px, 900px"><source type="image/png" srcset="/assets/keyboard.c98d0109_ZdIJDG.png 400w,/assets/keyboard.c98d0109_ZYqczx.png 900w" sizes="(max-width: 900px) 400px, 900px">
<img width="900" height="506" src="/assets/keyboard.c98d0109_JzyMQ.png" loading="lazy" decoding="async" alt="Developing on the Framework Laptop" class="object-cover w-full h-64 mb-6 rounded shadow-lg bg-gray-400 dark:bg-slate-700">
</picture>
</a>
<h3 class="mb-2 text-xl font-bold leading-snug sm:text-2xl font-heading">
<a href="/2022/08/25/developing-on-the-framework-laptop/" class="hover:text-primary-600 underline underline-offset-4 decoration-1 decoration-dotted transition ease-in duration-200">
Developing on the Framework Laptop
</a>
</h3>
<p class="text-gray-700 dark:text-gray-400">Earlier this year I bought the 11th gen Framework Laptop to develop on. I share what I liked and disliked and how I got on with it. </p>
</article><article class="mb-6 transition">
<a href="/2021/06/08/build-your-own-pico-powered-midi-controller-for-35/" class="hover:text-primary-600 underline underline-offset-4 decoration-1 decoration-dotted transition ease-in duration-200">
<picture>
<source type="image/avif" srcset="/assets/animation.fee8df7d_Z8DCSV.avif 400w,/assets/animation.fee8df7d_1xKSij.avif 900w" sizes="(max-width: 900px) 400px, 900px"><source type="image/webp" srcset="/assets/animation.fee8df7d_zGb3P.webp 400w,/assets/animation.fee8df7d_2h6Hg5.webp 900w" sizes="(max-width: 900px) 400px, 900px"><source type="image/png" srcset="/assets/animation.fee8df7d_ZNk0Xz.png 400w,/assets/animation.fee8df7d_Z1z1sTq.png 900w" sizes="(max-width: 900px) 400px, 900px">
<img width="900" height="506" src="/assets/animation.fee8df7d_6YP7K.png" loading="lazy" decoding="async" alt="Build Your Own Pico Powered Midi Controller for $35" class="object-cover w-full h-64 mb-6 rounded shadow-lg bg-gray-400 dark:bg-slate-700">
</picture>
</a>
<h3 class="mb-2 text-xl font-bold leading-snug sm:text-2xl font-heading">
<a href="/2021/06/08/build-your-own-pico-powered-midi-controller-for-35/" class="hover:text-primary-600 underline underline-offset-4 decoration-1 decoration-dotted transition ease-in duration-200">
Build Your Own Pico Powered Midi Controller for $35
</a>
</h3>
<p class="text-gray-700 dark:text-gray-400">The Pico RGB keypad base from pimoroni is a DIY kit that takes the Raspberry Pi Pico and gives you an a 16 button matrix of rgb LEDs, ready to program however you like using MicroPython or CircuitPython.</p>
</article>
</div>
</section><section class="px-4 py-16 mx-auto max-w-6xl lg:py-20">
<div class="flex flex-col mb-6 lg:justify-between lg:flex-row md:mb-8">
<h2 class="max-w-lg mb-2 text-3xl font-bold tracking-tight sm:text-4xl sm:leading-none lg:mb-5 group font-heading">
<span class="inline-block mb-1 sm:mb-4">Recent Videos</span>
</h2>
</div>
<div class="grid gap-6 row-gap-5 md:grid-cols-1 lg:grid-cols-3 -mb-6">
<lite-youtube videoid="k4qh83m1jg0" class="mb-6" style="background-image: url('https://i.ytimg.com/vi/k4qh83m1jg0/hqdefault.jpg');"></lite-youtube>
<lite-youtube videoid="evAb2x34Jqk" class="mb-6" style="background-image: url('https://i.ytimg.com/vi/evAb2x34Jqk/hqdefault.jpg');"></lite-youtube>
<lite-youtube videoid="ewXANEIC8pY" class="mb-6" style="background-image: url('https://i.ytimg.com/vi/ewXANEIC8pY/hqdefault.jpg');"></lite-youtube>
</div>
</section><section class="relative astro-LWWYAVEQ">
<div class="max-w-6xl mx-auto px-4 sm:px-6 astro-LWWYAVEQ">
<div class="py-12 md:py-20 astro-LWWYAVEQ">
<div class="max-w-3xl mx-auto text-center p-6 rounded-md shadow-xl dark:shadow-none astro-LWWYAVEQ">
<h2 class="text-4xl md:text-4xl font-bold leading-tighter tracking-tighter mb-4 font-heading astro-LWWYAVEQ">
Subscribe for Exclusives
</h2>
<p class="text-xl text-gray-600 dark:text-slate-400 astro-LWWYAVEQ">
My monthly newsletter shares exclusive articles you won't find elsewhere, tools and code. No spam, unsubscribe any time.
</p>
<div class="mt-6 astro-LWWYAVEQ">
<script defer src="https://unpkg.com/@tryghost/portal@latest/umd/portal.min.js" data-ghost="https://newsletter.ianwootten.co.uk" data-api="https://newsletter.ianwootten.co.uk/ghost/api/content/" data-key="e8ef5be0fe96aacc76c64de1ed"></script>
<form class="text-right astro-LWWYAVEQ" data-members-form>
<input class="mt-1 block w-full px-3 py-2 bg-white border border-slate-300 rounded-md text-sm shadow-sm dark:placeholder-slate-700 dark:text-slate-900 focus:outline-none focus:border-sky-500 focus:ring-1 focus:ring-sky-500 astro-LWWYAVEQ" placeholder="Your email address..." type="email" name="email" required="true" data-members-email>
<button class="mt-3 btn text-white bg-primary-600 hover:bg-primary-800 mb-4 sm:mb-0 astro-LWWYAVEQ" type="submit">Subscribe</button>
<strong class="feedback astro-LWWYAVEQ">Thanks so much! Check your inbox for an activation link.</strong>
</form>
</div>
</div>
</div>
</div>
</section>
</main><footer class="border-t border-gray-200 dark:border-slate-800">
<div class="max-w-6xl mx-auto px-4 sm:px-6">
<div class="md:flex md:items-center md:justify-between py-6 md:py-8">
<ul class="flex mb-4 md:order-1 -ml-2 md:ml-4 md:mb-0">
<li>
<a class="text-gray-500 dark:text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-700 focus:outline-none focus:ring-4 focus:ring-gray-200 dark:focus:ring-gray-700 rounded-lg text-sm p-2.5 inline-flex items-center" aria-label="Twitter" href="https://twitter.com/iwootten">
<svg viewBox="0 0 24 24" class="w-5 h-5" astro-icon="tabler:brand-twitter"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M22 4.01c-1 .49-1.98.689-3 .99-1.121-1.265-2.783-1.335-4.38-.737S11.977 6.323 12 8v1c-3.245.083-6.135-1.395-8-4 0 0-4.182 7.433 4 11-1.872 1.247-3.739 2.088-6 2 3.308 1.803 6.913 2.423 10.034 1.517 3.58-1.04 6.522-3.723 7.651-7.742a13.84 13.84 0 0 0 .497-3.753C20.18 7.773 21.692 5.25 22 4.009z"/></svg>
</a>
</li>
<li>
<a class="text-gray-500 dark:text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-700 focus:outline-none focus:ring-4 focus:ring-gray-200 dark:focus:ring-gray-700 rounded-lg text-sm p-2.5 inline-flex items-center" aria-label="YouTube" href="https://youtube.com/IanWootten">
<svg viewBox="0 0 24 24" class="w-5 h-5" astro-icon="tabler:brand-youtube"><g fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" class="icon-tabler"><rect width="18" height="14" x="3" y="5" rx="4"/><path d="m10 9 5 3-5 3z"/></g></svg>
</a>
</li>
<li>
<a class="text-gray-500 dark:text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-700 focus:outline-none focus:ring-4 focus:ring-gray-200 dark:focus:ring-gray-700 rounded-lg text-sm p-2.5 inline-flex items-center" aria-label="Github" href="https://github.com/iwootten">
<svg viewBox="0 0 24 24" class="w-5 h-5" astro-icon="tabler:brand-github"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 19c-4.3 1.4-4.3-2.5-6-3m12 5v-3.5c0-1 .1-1.4-.5-2 2.8-.3 5.5-1.4 5.5-6a4.6 4.6 0 0 0-1.3-3.2 4.2 4.2 0 0 0-.1-3.2s-1.1-.3-3.5 1.3a12.3 12.3 0 0 0-6.2 0C6.5 2.8 5.4 3.1 5.4 3.1a4.2 4.2 0 0 0-.1 3.2A4.6 4.6 0 0 0 4 9.5c0 4.6 2.7 5.7 5.5 6-.6.6-.6 1.2-.5 2V21"/></svg>
</a>
</li>
<li>
<a class="text-gray-500 dark:text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-700 focus:outline-none focus:ring-4 focus:ring-gray-200 dark:focus:ring-gray-700 rounded-lg text-sm p-2.5 inline-flex items-center" aria-label="LinkedIn" href="https://linkedin.com/in/iwootten">
<svg viewBox="0 0 24 24" class="w-5 h-5" astro-icon="tabler:brand-linkedin"><g fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" class="icon-tabler"><rect width="16" height="16" x="4" y="4" rx="2"/><path d="M8 11v5M8 8v.01M12 16v-5M16 16v-3a2 2 0 0 0-4 0"/></g></svg>
</a>
</li>
<li>
<a class="text-gray-500 dark:text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-700 focus:outline-none focus:ring-4 focus:ring-gray-200 dark:focus:ring-gray-700 rounded-lg text-sm p-2.5 inline-flex items-center" aria-label="RSS" href="/rss.xml">
<svg viewBox="0 0 24 24" class="w-5 h-5" astro-icon="tabler:rss"><g fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" class="icon-tabler"><circle cx="5" cy="19" r="1"/><path d="M4 4a16 16 0 0 1 16 16M4 11a9 9 0 0 1 9 9"/></g></svg>
</a>
</li>
</ul>
<div class="text-sm text-gray-700 mr-4 dark:text-slate-400">
© 2003-2024 Ian Wootten
</div>
</div>
</div>
</footer>
<script>
// Set "light" theme as default
// if (!localStorage.theme) {
// localStorage.theme = "light";
// }
if (
localStorage.theme === 'dark' ||
(!('theme' in localStorage) && window.matchMedia('(prefers-color-scheme: dark)').matches)
) {
document.documentElement.classList.add('dark');
} else {
document.documentElement.classList.remove('dark');
}
function attachEvent(selector, event, fn) {
const matches = document.querySelectorAll(selector);
if (matches && matches.length) {
matches.forEach((elem) => {
elem.addEventListener(event, () => fn(elem), false);
});
}
}
window.onload = function () {
attachEvent('[data-aw-toggle-menu]', 'click', function (elem) {
elem.classList.toggle('expanded');
document.body.classList.toggle('overflow-hidden');
document.getElementById('menu')?.classList.toggle('hidden');
});
attachEvent('[data-aw-toggle-color-scheme]', 'click', function () {
document.documentElement.classList.toggle('dark');
localStorage.theme = document.documentElement.classList.contains('dark') ? 'dark' : 'light';
});
};
window.onpageshow = function () {
const elem = document.querySelector('[data-aw-toggle-menu]');
if (elem) {
elem.classList.remove('expanded');
}
document.body.classList.remove('overflow-hidden');
document.getElementById('menu')?.classList.add('hidden');
};
</script>
</body>
</html>