<?xml version="1.0" encoding="utf-8"?><?xml-stylesheet type="text/xsl" href="atom.xsl"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <id>https://mikeq95blog.uk/en/blog</id>
    <title>mikeq95's blog Blog</title>
    <updated>2026-06-04T00:00:00.000Z</updated>
    <generator>https://github.com/jpmonette/feed</generator>
    <link rel="alternate" href="https://mikeq95blog.uk/en/blog"/>
    <subtitle>mikeq95's blog Blog</subtitle>
    <icon>https://mikeq95blog.uk/en/img/favicon.ico</icon>
    <entry>
        <title type="html"><![CDATA[About This Blog]]></title>
        <id>https://mikeq95blog.uk/en/blog/about</id>
        <link href="https://mikeq95blog.uk/en/blog/about"/>
        <updated>2026-06-04T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[About Me]]></summary>
        <content type="html"><![CDATA[<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="about-me">About Me<a href="https://mikeq95blog.uk/en/blog/about#about-me" class="hash-link" aria-label="Direct link to About Me" title="Direct link to About Me" translate="no">​</a></h2>
<p>Born after 2005, Gen Z, sophomore majoring in Electronic Information Engineering. I play basketball, game (LoL, CS2), and I'm learning English on the side — not great at it yet, but working on it.</p>
<p>Science student. My writing has always been pretty plain. But I think a good article has only one standard: the reader can understand it. That, I can manage.</p>
<!-- -->
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-this-blog-is-for">What This Blog Is For<a href="https://mikeq95blog.uk/en/blog/about#what-this-blog-is-for" class="hash-link" aria-label="Direct link to What This Blog Is For" title="Direct link to What This Blog Is For" translate="no">​</a></h2>
<p>Written for myself. To record things I've figured out, and to verify whether I've actually figured them out. If you can follow along too, great.</p>
<p>The content is mostly technical: AI tools, Mac development, things I've used and found worth writing down. You know the feeling — a lot of GitHub projects hit you with "set up your environment" right at step one. I don't want to write like that.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="about-this-site">About This Site<a href="https://mikeq95blog.uk/en/blog/about#about-this-site" class="hash-link" aria-label="Direct link to About This Site" title="Direct link to About This Site" translate="no">​</a></h2>
<p>No ads, and there won't be. I can guarantee that. I hate ads, and I don't want anyone here to be interrupted — including me, because I'm a reader here too.</p>
<p>I care about the experience. The site should be fast, pages should be clean, open it and you don't have to think — just find what you want to read.</p>
<p>As for making money, I'll figure that out later. But only one condition: it won't come at the cost of the experience.</p>
<p>I don't really care how many people read this. I care about how well I write.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="summary">Summary<a href="https://mikeq95blog.uk/en/blog/about#summary" class="hash-link" aria-label="Direct link to Summary" title="Direct link to Summary" translate="no">​</a></h2>
<p>okay, that's everything I want this site to be.</p>
<p>There's a Chinese saying: "知行合一" — to unify knowing and doing. I'll hold myself to that: turn what I think, and what I demand of myself, into reality.</p>]]></content>
        <category label="About" term="About"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[CodeGraph: Help Claude Code Work Smarter, Cut Token Usage in Half]]></title>
        <id>https://mikeq95blog.uk/en/blog/2026/06/03/codegraph-claude-code-knowledge-graph</id>
        <link href="https://mikeq95blog.uk/en/blog/2026/06/03/codegraph-claude-code-knowledge-graph"/>
        <updated>2026-06-03T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[I came across a GitHub project today — CodeGraph, 38k+ stars, MIT licensed. The core idea: pre-build your codebase into a knowledge graph so Claude Code can query it directly, instead of grep-scanning files every time. I installed it and tried it out — on average, 16% cost savings and 58% fewer tool calls.]]></summary>
        <content type="html"><![CDATA[<p>I came across a GitHub project today — <a href="https://github.com/colbymchenry/codegraph" target="_blank" rel="noopener noreferrer" class="">CodeGraph</a>, 38k+ stars, MIT licensed. The core idea: <strong>pre-build your codebase into a knowledge graph so Claude Code can query it directly, instead of grep-scanning files every time</strong>. I installed it and tried it out — on average, 16% cost savings and 58% fewer tool calls.</p>
<!-- -->
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="why-claude-code-wastes-tokens">Why Claude Code "Wastes" Tokens<a href="https://mikeq95blog.uk/en/blog/2026/06/03/codegraph-claude-code-knowledge-graph#why-claude-code-wastes-tokens" class="hash-link" aria-label="Direct link to Why Claude Code &quot;Wastes&quot; Tokens" title="Direct link to Why Claude Code &quot;Wastes&quot; Tokens" translate="no">​</a></h2>
<p>When you ask Claude Code an architecture question — like "how does this request reach the database?" — it first spins up an Explore sub-agent, runs a bunch of grep/ls/Read operations to find files, and only then starts analyzing. <strong>The whole exploration process burns tokens</strong>, and a lot of the time it reads a bunch of irrelevant files along the way.</p>
<p>CodeGraph's approach: do all that exploration work up front, index it into a local SQLite database. Claude Code queries it directly — one tool call returns the source code of relevant symbols, call graphs, and dependency relationships, without scanning files.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="installation">Installation<a href="https://mikeq95blog.uk/en/blog/2026/06/03/codegraph-claude-code-knowledge-graph#installation" class="hash-link" aria-label="Direct link to Installation" title="Direct link to Installation" translate="no">​</a></h2>
<p><strong>Install the CLI</strong> (macOS/Linux, no Node.js required):</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">curl -fsSL https://raw.githubusercontent.com/colbymchenry/codegraph/main/install.sh | sh</span><br></div></code></pre></div></div>
<p>After installing, <strong>open a new terminal</strong> — otherwise the <code>codegraph</code> command won't be found.</p>
<p><strong>Hook into Claude Code</strong>:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">codegraph install</span><br></div></code></pre></div></div>
<p>It auto-detects which AI tools you have installed (Claude Code, Cursor, Gemini CLI, etc.) — just select Claude Code, no need to check anything else.</p>
<p><strong>Initialize a project</strong>:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">cd your-project</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">codegraph init -i</span><br></div></code></pre></div></div>
<p><code>-i</code> is <code>--index</code> — creates the directory and indexes the codebase in one step. After that, a file watcher handles incremental updates automatically — no manual management needed.</p>
<p><strong>How to tell if a project is already initialized?</strong></p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">ls your-project/.codegraph</span><br></div></code></pre></div></div>
<p>If the folder exists, it's been indexed. If not, run <code>codegraph init -i</code> once.</p>]]></content>
        <category label="GitHub" term="GitHub"/>
        <category label="AI" term="AI"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[GSAP + Claude Code — Add Smooth Animations to Your Website]]></title>
        <id>https://mikeq95blog.uk/en/blog/2026/06/02/gsap-claude-code-web-animation</id>
        <link href="https://mikeq95blog.uk/en/blog/2026/06/02/gsap-claude-code-web-animation"/>
        <updated>2026-06-02T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[I recently came across an interesting GitHub project — gsap-skills, an official GSAP AI Skills package designed to "teach" Claude Code how to use the GSAP animation library correctly.]]></summary>
        <content type="html"><![CDATA[<p>I recently came across an interesting GitHub project — <a href="https://github.com/greensock/gsap-skills" target="_blank" rel="noopener noreferrer" class="">gsap-skills</a>, an official GSAP AI Skills package designed to "teach" Claude Code how to use the GSAP animation library correctly.</p>
<p>Quick note: I initially thought GSAP was for video editing, like HeyGen — turns out it's completely different. <strong>GSAP is for web animations</strong> — the kind you see in a browser: elements flying in, scroll parallax, number counters rolling up, all rendered live on the page, not as video files. Once I got that straight, I decided to install it in Claude Code and give it a shot.</p>
<!-- -->
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-is-gsap">What Is GSAP<a href="https://mikeq95blog.uk/en/blog/2026/06/02/gsap-claude-code-web-animation#what-is-gsap" class="hash-link" aria-label="Direct link to What Is GSAP" title="Direct link to What Is GSAP" translate="no">​</a></h2>
<p><a href="https://gsap.com/" target="_blank" rel="noopener noreferrer" class="">GSAP</a> (GreenSock Animation Platform) is currently the most popular JavaScript web animation library. Its core strengths:</p>
<ul>
<li class=""><strong>Fine-grained control</strong>: pause, reverse, and precisely time every animation</li>
<li class=""><strong>ScrollTrigger</strong>: handles scroll-linked animations — parallax, scroll-triggered effects, pinned elements, all straightforward</li>
<li class=""><strong>Timeline</strong>: sequence multiple elements' animations in just a few lines</li>
<li class=""><strong>Performance</strong>: operates on transforms under the hood, on par with CSS animations</li>
</ul>
<p>Compared to CSS animations:</p>
<table><thead><tr><th></th><th>CSS Animations</th><th>GSAP</th></tr></thead><tbody><tr><td>Language</td><td>CSS</td><td>JavaScript</td></tr><tr><td>Control</td><td>Limited</td><td>Extremely powerful</td></tr><tr><td>Scroll-linked</td><td>Hard to do</td><td>ScrollTrigger handles it</td></tr><tr><td>Complex sequences</td><td>Painful to write</td><td>Timeline, a few lines</td></tr><tr><td>Performance</td><td>Good</td><td>Equally good</td></tr></tbody></table>
<p>Good news: <strong>GSAP is now completely free</strong> — including previously paid-only plugins like SplitText and MorphSVG. Everything is open to everyone, including commercial use.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-is-gsap-skills">What Is gsap-skills<a href="https://mikeq95blog.uk/en/blog/2026/06/02/gsap-claude-code-web-animation#what-is-gsap-skills" class="hash-link" aria-label="Direct link to What Is gsap-skills" title="Direct link to What Is gsap-skills" translate="no">​</a></h2>
<p>AI models' knowledge of GSAP may be outdated — for example, how ScrollTrigger is written today, or how to clean up in React. With <code>gsap-skills</code> installed, Claude Code can write code using the correct APIs, knows how each plugin works, and follows React best practices.</p>
<p>It includes 8 skills:</p>
<table><thead><tr><th>Skill</th><th>Content</th></tr></thead><tbody><tr><td>gsap-core</td><td>Core APIs: to / from / fromTo, easing, stagger</td></tr><tr><td>gsap-timeline</td><td>Timelines, sequencing, labels</td></tr><tr><td>gsap-scrolltrigger</td><td>Scroll animations, pinning, scrub</td></tr><tr><td>gsap-plugins</td><td>SplitText, Flip, Draggable, and all other plugins</td></tr><tr><td>gsap-react</td><td>useGSAP hook, cleanup, SSR</td></tr><tr><td>gsap-performance</td><td>Performance optimization tips</td></tr><tr><td>gsap-frameworks</td><td>Vue, Svelte, and other frameworks</td></tr><tr><td>gsap-utils</td><td>gsap.utils helper functions</td></tr></tbody></table>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="installing-gsap-skills">Installing gsap-skills<a href="https://mikeq95blog.uk/en/blog/2026/06/02/gsap-claude-code-web-animation#installing-gsap-skills" class="hash-link" aria-label="Direct link to Installing gsap-skills" title="Direct link to Installing gsap-skills" translate="no">​</a></h2>
<p>Run in your terminal:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">npx skills add https://github.com/greensock/gsap-skills</span><br></div></code></pre></div></div>
<p>The first run will prompt you to install <code>skills@1.5.9</code> — enter <code>y</code> to confirm.</p>
<p>You'll then be asked which skills to install. <strong>Use spacebar to check, Enter to confirm.</strong> For a blog project (Docusaurus / React), these four are enough:</p>
<ul>
<li class="">✅ gsap-core</li>
<li class="">✅ gsap-scrolltrigger</li>
<li class="">✅ gsap-timeline</li>
<li class="">✅ gsap-react</li>
</ul>
<p>For the remaining prompts:</p>
<ul>
<li class=""><strong>Agent</strong>: select <code>Claude Code</code></li>
<li class=""><strong>Installation scope</strong>: select <code>Global</code> (global install — works across all projects without reinstalling)</li>
<li class=""><strong>Installation method</strong>: select <code>Symlink</code> (recommended — auto-syncs when the skill updates)</li>
</ul>
<p>After installation, the skills are saved to <code>~/.claude/skills/</code>.</p>
<blockquote>
<p><strong>Can't find the <code>.claude</code> folder?</strong> It's hidden. In Finder, press <strong>⌘ + Shift + . (period)</strong> to show all hidden files. Press again to hide them.</p>
</blockquote>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="how-to-use-it">How to Use It<a href="https://mikeq95blog.uk/en/blog/2026/06/02/gsap-claude-code-web-animation#how-to-use-it" class="hash-link" aria-label="Direct link to How to Use It" title="Direct link to How to Use It" translate="no">​</a></h2>
<p>No special commands needed after installation. <strong>Just describe the animation you want in Claude Code</strong>, and Claude will automatically use the relevant skill to write correct code.</p>
<p>For example:</p>
<blockquote>
<p>"Add an entrance animation to the title on my blog homepage using GSAP"</p>
</blockquote>
<blockquote>
<p>"Use ScrollTrigger to make an animation trigger when the user scrolls to a certain section"</p>
</blockquote>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="real-example-scroll-in-animation-for-blog-post-cards">Real Example: Scroll-In Animation for Blog Post Cards<a href="https://mikeq95blog.uk/en/blog/2026/06/02/gsap-claude-code-web-animation#real-example-scroll-in-animation-for-blog-post-cards" class="hash-link" aria-label="Direct link to Real Example: Scroll-In Animation for Blog Post Cards" title="Direct link to Real Example: Scroll-In Animation for Blog Post Cards" translate="no">​</a></h2>
<p>Say your blog has a post list page where each card flies in from below when the user scrolls to it — a very common effect.</p>
<p>First, install GSAP:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">npm install gsap</span><br></div></code></pre></div></div>
<p>Then in your React component:</p>
<div class="language-jsx codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-jsx codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword module" style="color:#00009f">import</span><span class="token plain"> </span><span class="token imports punctuation" style="color:#393A34">{</span><span class="token imports"> useEffect</span><span class="token imports punctuation" style="color:#393A34">,</span><span class="token imports"> useRef </span><span class="token imports punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword module" style="color:#00009f">from</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"react"</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword module" style="color:#00009f">import</span><span class="token plain"> </span><span class="token imports punctuation" style="color:#393A34">{</span><span class="token imports"> gsap </span><span class="token imports punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword module" style="color:#00009f">from</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"gsap"</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword module" style="color:#00009f">import</span><span class="token plain"> </span><span class="token imports punctuation" style="color:#393A34">{</span><span class="token imports"> </span><span class="token imports maybe-class-name">ScrollTrigger</span><span class="token imports"> </span><span class="token imports punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword module" style="color:#00009f">from</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"gsap/ScrollTrigger"</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">gsap</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">registerPlugin</span><span class="token punctuation" style="color:#393A34">(</span><span class="token maybe-class-name">ScrollTrigger</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword module" style="color:#00009f">export</span><span class="token plain"> </span><span class="token keyword module" style="color:#00009f">default</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">function</span><span class="token plain"> </span><span class="token function maybe-class-name" style="color:#d73a49">BlogCard</span><span class="token punctuation" style="color:#393A34">(</span><span class="token parameter punctuation" style="color:#393A34">{</span><span class="token parameter"> title</span><span class="token parameter punctuation" style="color:#393A34">,</span><span class="token parameter"> date</span><span class="token parameter punctuation" style="color:#393A34">,</span><span class="token parameter"> description </span><span class="token parameter punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> cardRef </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">useRef</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword null nil" style="color:#00009f">null</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token function" style="color:#d73a49">useEffect</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> ctx </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> gsap</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">context</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      gsap</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword module" style="color:#00009f">from</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">cardRef</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">current</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token literal-property property" style="color:#36acaa">y</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">60</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain">           </span><span class="token comment" style="color:#999988;font-style:italic">// flies in from 60px below</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token literal-property property" style="color:#36acaa">opacity</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain">      </span><span class="token comment" style="color:#999988;font-style:italic">// fades in from transparent</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token literal-property property" style="color:#36acaa">duration</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0.7</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token literal-property property" style="color:#36acaa">ease</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"power2.out"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token literal-property property" style="color:#36acaa">scrollTrigger</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">          </span><span class="token literal-property property" style="color:#36acaa">trigger</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> cardRef</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">current</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">          </span><span class="token literal-property property" style="color:#36acaa">start</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"top 85%"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">// triggers when element top enters 85% of viewport</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> cardRef</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword control-flow" style="color:#00009f">return</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:#393A34">=&gt;</span><span class="token plain"> ctx</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">revert</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// cleanup on unmount — prevents memory leaks</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword control-flow" style="color:#00009f">return</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">div</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">ref</span><span class="token tag script language-javascript script-punctuation punctuation" style="color:#393A34">=</span><span class="token tag script language-javascript punctuation" style="color:#393A34">{</span><span class="token tag script language-javascript" style="color:#00009f">cardRef</span><span class="token tag script language-javascript punctuation" style="color:#393A34">}</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">className</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">blog-card</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain-text">      </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">h2</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain">title</span><span class="token punctuation" style="color:#393A34">}</span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">h2</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain-text">      </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">span</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain">date</span><span class="token punctuation" style="color:#393A34">}</span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">span</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain-text">      </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">p</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain">description</span><span class="token punctuation" style="color:#393A34">}</span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">p</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain-text">    </span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">div</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div>
<p>The result: as the user scrolls down, each card flies in from below one by one, creating a layered entrance effect. Change <code>start: "top 85%"</code> to <code>"top 70%"</code> to trigger later — experiment until it feels right.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="summary">Summary<a href="https://mikeq95blog.uk/en/blog/2026/06/02/gsap-claude-code-web-animation#summary" class="hash-link" aria-label="Direct link to Summary" title="Direct link to Summary" translate="no">​</a></h2>
<p>GSAP is for <strong>web animations</strong> — not video. That's the important thing to get right first 😂.</p>
<p>The value of <code>gsap-skills</code> is that it lets Claude Code truly understand GSAP — not just write code, but write <em>correct</em> code: no outdated APIs, no missing cleanup in React. Setup takes five minutes. After that, just describe what you want and let Claude write it — no need to memorize any API.</p>
<p>If your blog or project needs scroll animations, page transitions, or element entrances, GSAP is the best open-source option out there right now.</p>]]></content>
        <category label="GitHub" term="GitHub"/>
        <category label="macOS" term="macOS"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Open-Source Alternative to Claude Design — My Hands-On with Open CoDesign]]></title>
        <id>https://mikeq95blog.uk/en/blog/2026/06/01/open-codesign-review</id>
        <link href="https://mikeq95blog.uk/en/blog/2026/06/01/open-codesign-review"/>
        <updated>2026-06-01T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Claude Design has been getting a lot of attention lately — you give it a prompt and it generates a page prototype instantly, which looks impressive. The problem is it requires a separate subscription, costs money, only works with Claude, and your data lives in the cloud. I started wondering if there's an open-source alternative. There is: Open CoDesign — MIT licensed, runs locally, supports your own API keys. Here's my experience with it.]]></summary>
        <content type="html"><![CDATA[<p>Claude Design has been getting a lot of attention lately — you give it a prompt and it generates a page prototype instantly, which looks impressive. The problem is it requires a separate subscription, costs money, only works with Claude, and your data lives in the cloud. I started wondering if there's an open-source alternative. There is: <a href="https://github.com/OpenCoworkAI/open-codesign" target="_blank" rel="noopener noreferrer" class="">Open CoDesign</a> — MIT licensed, runs locally, supports your own API keys. Here's my experience with it.</p>
<!-- -->
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-it-is">What It Is<a href="https://mikeq95blog.uk/en/blog/2026/06/01/open-codesign-review#what-it-is" class="hash-link" aria-label="Direct link to What It Is" title="Direct link to What It Is" translate="no">​</a></h2>
<p>Open CoDesign is a desktop AI design tool. The core idea is simple: <strong>you enter a prompt, it generates a viewable HTML prototype page</strong>. It's positioned as an open-source alternative to Claude Design, v0, and Lovable. Key points:</p>
<ul>
<li class=""><strong>Runs locally</strong> — your data stays on your machine</li>
<li class=""><strong>BYOK</strong> (Bring Your Own Key) — supports Claude, GPT, Gemini, and Ollama</li>
<li class=""><strong>MIT open-source</strong> — free to use; you only pay for your own model's API costs</li>
<li class=""><strong>Exports real files</strong> — HTML, PDF, PPTX, ZIP, all supported</li>
</ul>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="deployment">Deployment<a href="https://mikeq95blog.uk/en/blog/2026/06/01/open-codesign-review#deployment" class="hash-link" aria-label="Direct link to Deployment" title="Direct link to Deployment" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="requirements">Requirements<a href="https://mikeq95blog.uk/en/blog/2026/06/01/open-codesign-review#requirements" class="hash-link" aria-label="Direct link to Requirements" title="Direct link to Requirements" translate="no">​</a></h3>
<ul>
<li class="">Node.js v22+</li>
<li class="">pnpm 10.x</li>
</ul>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain"># Check Node version</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">node -v</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"># Install pnpm</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">npm install -g pnpm@10.33.4</span><br></div></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="clone--install">Clone &amp; Install<a href="https://mikeq95blog.uk/en/blog/2026/06/01/open-codesign-review#clone--install" class="hash-link" aria-label="Direct link to Clone &amp; Install" title="Direct link to Clone &amp; Install" translate="no">​</a></h3>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">git clone https://github.com/OpenCoworkAI/open-codesign.git</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">cd open-codesign</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">pnpm install</span><br></div></code></pre></div></div>
<p><code>pnpm install</code> takes a minute or two — wait for it to finish.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="start">Start<a href="https://mikeq95blog.uk/en/blog/2026/06/01/open-codesign-review#start" class="hash-link" aria-label="Direct link to Start" title="Direct link to Start" translate="no">​</a></h3>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">pnpm dev</span><br></div></code></pre></div></div>
<p>After a moment, an Electron window will appear. The first time, it asks you to configure a provider — paste in your Claude API key (<code>sk-ant-...</code>), test the connection, and you're ready to go.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="how-it-feels-in-practice">How It Feels in Practice<a href="https://mikeq95blog.uk/en/blog/2026/06/01/open-codesign-review#how-it-feels-in-practice" class="hash-link" aria-label="Direct link to How It Feels in Practice" title="Direct link to How It Feels in Practice" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="generation-speed">Generation Speed<a href="https://mikeq95blog.uk/en/blog/2026/06/01/open-codesign-review#generation-speed" class="hash-link" aria-label="Direct link to Generation Speed" title="Direct link to Generation Speed" translate="no">​</a></h3>
<p>With the Claude API, a medium-complexity page takes about 20–40 seconds to generate. During generation, there's an Agent panel on the left showing what the AI is doing in real time — which files it wrote, which tools it called. It's not a black box, and it's kind of interesting to watch.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="output-quality">Output Quality<a href="https://mikeq95blog.uk/en/blog/2026/06/01/open-codesign-review#output-quality" class="hash-link" aria-label="Direct link to Output Quality" title="Direct link to Output Quality" translate="no">​</a></h3>
<p>There are 15 built-in demo templates (landing pages, dashboards, pricing pages, chat UIs, etc.) — pick one and tweak the prompt, and you have a solid starting point. It also comes with 12 design skill modules that are automatically selected based on your prompt, so the output doesn't look like that typical generic "AI aesthetic."</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="comment-mode">Comment Mode<a href="https://mikeq95blog.uk/en/blog/2026/06/01/open-codesign-review#comment-mode" class="hash-link" aria-label="Direct link to Comment Mode" title="Direct link to Comment Mode" translate="no">​</a></h3>
<p>A genuinely useful feature: click any element in the preview and leave a comment, then let the AI rewrite just that section without having to re-describe the whole page. Much more precise than modifying the prompt from scratch.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="ai-sliders">AI Sliders<a href="https://mikeq95blog.uk/en/blog/2026/06/01/open-codesign-review#ai-sliders" class="hash-link" aria-label="Direct link to AI Sliders" title="Direct link to AI Sliders" translate="no">​</a></h3>
<p>After generation, the AI automatically identifies "tunable parameters" — like primary color, font size, spacing — and presents them as sliders. No need to write "change the button color to blue" in a new prompt.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="vs-claude-design">vs. Claude Design<a href="https://mikeq95blog.uk/en/blog/2026/06/01/open-codesign-review#vs-claude-design" class="hash-link" aria-label="Direct link to vs. Claude Design" title="Direct link to vs. Claude Design" translate="no">​</a></h2>
<table><thead><tr><th></th><th style="text-align:center">Open CoDesign</th><th style="text-align:center">Claude Design</th></tr></thead><tbody><tr><td>Open-source</td><td style="text-align:center">✅ MIT</td><td style="text-align:center">❌</td></tr><tr><td>Runs locally</td><td style="text-align:center">✅</td><td style="text-align:center">❌ Cloud</td></tr><tr><td>Multi-model support</td><td style="text-align:center">✅ 20+</td><td style="text-align:center">❌ Claude only</td></tr><tr><td>Price</td><td style="text-align:center">✅ Free (pay your own API)</td><td style="text-align:center">💳 Subscription</td></tr><tr><td>Data privacy</td><td style="text-align:center">✅ Local</td><td style="text-align:center">❌ Cloud-processed</td></tr></tbody></table>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="summary">Summary<a href="https://mikeq95blog.uk/en/blog/2026/06/01/open-codesign-review#summary" class="hash-link" aria-label="Direct link to Summary" title="Direct link to Summary" translate="no">​</a></h2>
<p>If you already have a Claude API key, the setup cost is low — worth trying.</p>]]></content>
        <category label="GitHub" term="GitHub"/>
        <category label="macOS" term="macOS"/>
        <category label="AI" term="AI"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Download YouTube Videos Using a Python Script]]></title>
        <id>https://mikeq95blog.uk/en/blog/2026/05/29/download-youtube-videos-using-a-python-script</id>
        <link href="https://mikeq95blog.uk/en/blog/2026/05/29/download-youtube-videos-using-a-python-script"/>
        <updated>2026-05-29T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Want to save YouTube videos locally? This post walks through a Python script that handles everything for you — set it up once, then just swap the URL each time.]]></summary>
        <content type="html"><![CDATA[<p>Want to save YouTube videos locally? This post walks through a Python script that handles everything for you — set it up once, then just swap the URL each time.</p>
<!-- -->
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="setting-up-the-environment">Setting Up the Environment<a href="https://mikeq95blog.uk/en/blog/2026/05/29/download-youtube-videos-using-a-python-script#setting-up-the-environment" class="hash-link" aria-label="Direct link to Setting Up the Environment" title="Direct link to Setting Up the Environment" translate="no">​</a></h2>
<p>Your Mac needs the following four tools. Install them in order.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="homebrew">Homebrew<a href="https://mikeq95blog.uk/en/blog/2026/05/29/download-youtube-videos-using-a-python-script#homebrew" class="hash-link" aria-label="Direct link to Homebrew" title="Direct link to Homebrew" translate="no">​</a></h3>
<p>macOS package manager — the foundation for installing everything else.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"</span><br></div></code></pre></div></div>
<p>Verify:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">brew --version</span><br></div></code></pre></div></div>
<p>✅ Success: shows <code>Homebrew 4.x.x</code> ❌ Failure: shows <code>command not found</code></p>
<hr>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="ffmpeg">ffmpeg<a href="https://mikeq95blog.uk/en/blog/2026/05/29/download-youtube-videos-using-a-python-script#ffmpeg" class="hash-link" aria-label="Direct link to ffmpeg" title="Direct link to ffmpeg" translate="no">​</a></h3>
<p>Merges audio and video streams — without it you'll only get a silent video.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">brew install ffmpeg</span><br></div></code></pre></div></div>
<p>Verify:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">ffmpeg -version</span><br></div></code></pre></div></div>
<p>✅ Success: shows <code>ffmpeg version 7.x.x</code> ❌ Failure: shows <code>command not found</code></p>
<hr>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="nodejs">Node.js<a href="https://mikeq95blog.uk/en/blog/2026/05/29/download-youtube-videos-using-a-python-script#nodejs" class="hash-link" aria-label="Direct link to Node.js" title="Direct link to Node.js" translate="no">​</a></h3>
<p>Solves YouTube's JS encryption challenge — without it all format options are lost.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">brew install node</span><br></div></code></pre></div></div>
<p>Verify:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">node --version</span><br></div></code></pre></div></div>
<p>✅ Success: shows <code>v26.x.x</code> ❌ Failure: shows <code>command not found</code></p>
<hr>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="yt-dlp">yt-dlp<a href="https://mikeq95blog.uk/en/blog/2026/05/29/download-youtube-videos-using-a-python-script#yt-dlp" class="hash-link" aria-label="Direct link to yt-dlp" title="Direct link to yt-dlp" translate="no">​</a></h3>
<p>The core download library.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">pip3 install yt-dlp --break-system-packages</span><br></div></code></pre></div></div>
<p>Verify:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">yt-dlp --version</span><br></div></code></pre></div></div>
<p>✅ Success: shows <code>2026.x.xx</code> ❌ Failure: shows <code>command not found</code></p>
<hr>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="two-extra-configuration-steps">Two Extra Configuration Steps<a href="https://mikeq95blog.uk/en/blog/2026/05/29/download-youtube-videos-using-a-python-script#two-extra-configuration-steps" class="hash-link" aria-label="Direct link to Two Extra Configuration Steps" title="Direct link to Two Extra Configuration Steps" translate="no">​</a></h3>
<p><strong>Grant Terminal Full Disk Access</strong> (needed to read Safari cookies)</p>
<p>System Settings → Privacy &amp; Security → Full Disk Access → Add "Terminal"</p>
<p><strong>Enable a proxy</strong> (required to access YouTube outside China)</p>
<blockquote>
<p>I'm definitely not going to teach you that one!</p>
</blockquote>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="get-the-code">Get the Code<a href="https://mikeq95blog.uk/en/blog/2026/05/29/download-youtube-videos-using-a-python-script#get-the-code" class="hash-link" aria-label="Direct link to Get the Code" title="Direct link to Get the Code" translate="no">​</a></h2>
<p>You can download the script I wrote, or write it yourself (or have AI write it — see the next section).</p>
<p><a href="https://drive.google.com/file/d/14lFupv6bSw-cicSJ2KxoWYJgkII1uHeZ/view?usp=share_link" target="_blank" rel="noopener noreferrer" class="">Download main.py</a></p>
<p>Script contents:</p>
<div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-python codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> subprocess</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> sys</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> os</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># ── Configuration ────────────────────────────────────────────────────────────</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">VIDEO_URL  </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"XXXX"</span><span class="token plain">                           </span><span class="token comment" style="color:#999988;font-style:italic"># Replace with a real YouTube URL</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">OUTPUT_DIR </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> os</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">path</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">expanduser</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"~/Desktop"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic"># Output to Desktop</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">NODE_PATH  </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"/opt/homebrew/bin/node"</span><span class="token plain">         </span><span class="token comment" style="color:#999988;font-style:italic"># Node.js path (installed via Homebrew)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># ─────────────────────────────────────────────────────────────────────────────</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">def</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">download_video</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">url</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token builtin">str</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> output_dir</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token builtin">str</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">-</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">None</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token triple-quoted-string string" style="color:#e3116c">"""</span><br></div><div class="token-line" style="color:#393A34"><span class="token triple-quoted-string string" style="color:#e3116c">    Calls the yt-dlp CLI to download a YouTube video in H.264 MP4 format.</span><br></div><div class="token-line" style="color:#393A34"><span class="token triple-quoted-string string" style="color:#e3116c">    """</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    output_template </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> os</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">path</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">join</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">output_dir</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"%(title)s.%(ext)s"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    cmd </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token string" style="color:#e3116c">"yt-dlp"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic"># Prefer H.264 video stream + best audio</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token string" style="color:#e3116c">"--format"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"bestvideo[vcodec^=avc1]+bestaudio/bestvideo[ext=mp4]+bestaudio/best"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic"># Force MP4 container</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token string" style="color:#e3116c">"--merge-output-format"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"mp4"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic"># Specify Node.js path for solving YouTube's JS encryption</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token string" style="color:#e3116c">"--js-runtimes"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token string-interpolation string" style="color:#e3116c">f"node:</span><span class="token string-interpolation interpolation punctuation" style="color:#393A34">{</span><span class="token string-interpolation interpolation">NODE_PATH</span><span class="token string-interpolation interpolation punctuation" style="color:#393A34">}</span><span class="token string-interpolation string" style="color:#e3116c">"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic"># Download JS challenge decryption script from GitHub (requires internet on first run)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token string" style="color:#e3116c">"--remote-components"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"ejs:github"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic"># Read Safari cookies to bypass bot detection</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token string" style="color:#e3116c">"--cookies-from-browser"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"safari"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic"># Output file path template</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token string" style="color:#e3116c">"--output"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> output_template</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        url</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">print</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string-interpolation string" style="color:#e3116c">f"[INFO] Starting download: </span><span class="token string-interpolation interpolation punctuation" style="color:#393A34">{</span><span class="token string-interpolation interpolation">url</span><span class="token string-interpolation interpolation punctuation" style="color:#393A34">}</span><span class="token string-interpolation string" style="color:#e3116c">"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">print</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string-interpolation string" style="color:#e3116c">f"[INFO] Output directory: </span><span class="token string-interpolation interpolation punctuation" style="color:#393A34">{</span><span class="token string-interpolation interpolation">output_dir</span><span class="token string-interpolation interpolation punctuation" style="color:#393A34">}</span><span class="token string-interpolation string" style="color:#e3116c">\n"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    result </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> subprocess</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">run</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">cmd</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> result</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">returncode </span><span class="token operator" style="color:#393A34">==</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">print</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"\n[✓] Download complete! Video saved to Desktop."</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">else</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">print</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"\n[✗] Download failed. Check the error output above."</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token builtin">file</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">sys</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">stderr</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        sys</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">exit</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">1</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> __name__ </span><span class="token operator" style="color:#393A34">==</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"__main__"</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic"># Supports passing a URL as a command-line argument: python3 main.py &lt;url&gt;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    url </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> sys</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">argv</span><span class="token punctuation" style="color:#393A34">[</span><span class="token number" style="color:#36acaa">1</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token builtin">len</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">sys</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">argv</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">1</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">else</span><span class="token plain"> VIDEO_URL</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> url </span><span class="token operator" style="color:#393A34">==</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"XXXX"</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">print</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"[✗] Please replace VIDEO_URL with a real URL, or pass it as a command-line argument."</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">              </span><span class="token builtin">file</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">sys</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">stderr</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">print</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"    Usage: python3 main.py \"YouTube URL\""</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token builtin">file</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">sys</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">stderr</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        sys</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">exit</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">1</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    download_video</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">url</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> OUTPUT_DIR</span><span class="token punctuation" style="color:#393A34">)</span><br></div></code></pre></div></div>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-lazy-approach-let-ai-write-the-code">The Lazy Approach: Let AI Write the Code<a href="https://mikeq95blog.uk/en/blog/2026/05/29/download-youtube-videos-using-a-python-script#the-lazy-approach-let-ai-write-the-code" class="hash-link" aria-label="Direct link to The Lazy Approach: Let AI Write the Code" title="Direct link to The Lazy Approach: Let AI Write the Code" translate="no">​</a></h2>
<p>Don't want to write the code yourself? Just paste one of these prompts into ChatGPT, DeepSeek, or Claude and they'll output a working script.</p>
<p><strong>English prompt (recommended — more stable output):</strong></p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">I need you to help me set up a YouTube video download environment on macOS and write a complete Python script.</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">## My Environment</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">- Device: MacBook (Apple Silicon, M-series chip)</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">- OS: macOS</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">## What I Need You To Do</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">### Step 1 — Check and Install Dependencies</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">Check whether the following tools are installed one by one. If not, provide the install command:</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">1. Homebrew: via https://brew.sh/</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">2. ffmpeg: via brew install ffmpeg</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">3. Node.js: via brew install node</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">4. yt-dlp: via pip3 install yt-dlp --break-system-packages</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">### Step 2 — Write the Python Script</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">Filename: youtube_downloader.py</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">Requirements:</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">- Use subprocess to call the yt-dlp CLI (do NOT use the yt_dlp Python API)</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">- Video format: H.264 codec, MP4 container</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">- Quality: automatically select the highest available quality</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">- Cookies: read from Safari (--cookies-from-browser safari)</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">- Node.js path: /opt/homebrew/bin/node</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">- Include --remote-components ejs:github to solve JS challenges</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">- Output directory: Desktop (~/Desktop)</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">- Accept video URL as a command-line argument: python3 youtube_downloader.py "YouTube URL"</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">- Add comments in English</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">### Step 3 — Tell Me How To Use It</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">Explain how to run the script in one sentence.</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">## Important Notes</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">- macOS root directory / is read-only — do NOT output files there</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">- Terminal needs Full Disk Access enabled in System Settings to read Safari cookies — please remind me to do this</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">- Do NOT use "ios" as the player_client — it does not support cookies</span><br></div></code></pre></div></div>
<blockquote>
<p>AI can write the code for you, but <strong>you still need to set up the environment yourself</strong> (the four tools above). If you don't want to do that manually either, use Claude Code or Codex to run the install commands automatically — just keep clicking yes.</p>
</blockquote>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="usage">Usage<a href="https://mikeq95blog.uk/en/blog/2026/05/29/download-youtube-videos-using-a-python-script#usage" class="hash-link" aria-label="Direct link to Usage" title="Direct link to Usage" translate="no">​</a></h2>
<p>Once the environment is set up, every download only takes one command.</p>
<p>Open Terminal and run:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">python3 ~/Downloads/main.py "paste your YouTube URL here"</span><br></div></code></pre></div></div>
<blockquote>
<p>If you saved <code>main.py</code> somewhere else, replace <code>~/Downloads/main.py</code> with the actual path. <code>~/Downloads</code> refers to your Downloads folder — no need to substitute your username.</p>
</blockquote>
<p>Example:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">python3 ~/Downloads/main.py "https://www.youtube.com/watch?v=5wvq8w7YBXU"</span><br></div></code></pre></div></div>
<p>Press Enter and wait — the video will appear on your <strong>Desktop</strong> when done.</p>
<hr>
<p><strong>Two things to check before each use:</strong></p>
<p>① Your proxy is active (e.g. Shadowrocket is connected)</p>
<p>② You're using a freshly opened Terminal window (not one that's been open for days)</p>
<p>You only need to set up the environment once. After that, any YouTube URL works.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="faq">FAQ<a href="https://mikeq95blog.uk/en/blog/2026/05/29/download-youtube-videos-using-a-python-script#faq" class="hash-link" aria-label="Direct link to FAQ" title="Direct link to FAQ" translate="no">​</a></h2>
<p><strong>What is Homebrew?</strong> I wrote a separate post about it — check that out.</p>
<p><strong>What video quality will I get?</strong> The highest available by default. This line in the script controls the resolution selection logic:</p>
<div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-python codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token string" style="color:#e3116c">"bestvideo[vcodec^=avc1]+bestaudio/bestvideo[ext=mp4]+bestaudio/best"</span><br></div></code></pre></div></div>
<p>It selects the highest-quality stream among all H.264-encoded video tracks.</p>
<p><strong>Terminal is stuck and nothing's happening?</strong> The first run downloads a decryption script from the internet, which can be slow on some networks. Make sure your proxy is active, or wait 1–2 minutes.</p>
<p><strong><code>command not found</code> error?</strong> A dependency didn't install correctly. Go back to the "Setting Up the Environment" section and verify each tool one by one.</p>
<p><strong><code>permission denied</code> or cookie read failure?</strong> Terminal doesn't have Full Disk Access. Go to System Settings → Privacy &amp; Security → Full Disk Access → Add "Terminal", then open a new Terminal window and try again.</p>
<p><strong>Download failed and you can't read the error?</strong> Check in order: ① Is your proxy on? ② Is yt-dlp up to date? (<code>pip3 install -U yt-dlp --break-system-packages</code>) ③ Is the URL complete and wrapped in quotes?</p>]]></content>
        <category label="macOS" term="macOS"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Introduction to Homebrew]]></title>
        <id>https://mikeq95blog.uk/en/blog/2026/05/28/homebrew-tutorials</id>
        <link href="https://mikeq95blog.uk/en/blog/2026/05/28/homebrew-tutorials"/>
        <updated>2026-05-28T00:00:00.000Z</updated>
        <summary type="html"><![CDATA["The most popular command-line package manager for macOS."]]></summary>
        <content type="html"><![CDATA[<blockquote>
<p>"The most popular command-line package manager for macOS."</p>
</blockquote>
<p>Still hunting down installers one by one on official websites? With Homebrew, one command handles everything — install, update, uninstall — all managed in one place. Say goodbye to manual downloads.</p>
<p>Homebrew is a package manager for macOS and Linux. Its core value in one sentence: <strong>manage all your software from the command line, unified.</strong></p>
<!-- -->
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="installing-homebrew">Installing Homebrew<a href="https://mikeq95blog.uk/en/blog/2026/05/28/homebrew-tutorials#installing-homebrew" class="hash-link" aria-label="Direct link to Installing Homebrew" title="Direct link to Installing Homebrew" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="in-china">In China<a href="https://mikeq95blog.uk/en/blog/2026/05/28/homebrew-tutorials#in-china" class="hash-link" aria-label="Direct link to In China" title="Direct link to In China" translate="no">​</a></h3>
<p>Due to network restrictions, using a domestic mirror is recommended: <a href="https://github.com/ineo6/homebrew-install" target="_blank" rel="noopener noreferrer" class="">source</a></p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">/bin/bash -c "$(curl -fsSL https://gitee.com/ineo6/homebrew-install/raw/master/install.sh)"</span><br></div></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="outside-china">Outside China<a href="https://mikeq95blog.uk/en/blog/2026/05/28/homebrew-tutorials#outside-china" class="hash-link" aria-label="Direct link to Outside China" title="Direct link to Outside China" translate="no">​</a></h3>
<p>Use the official script: <a href="https://brew.sh/" target="_blank" rel="noopener noreferrer" class="">source</a></p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"</span><br></div></code></pre></div></div>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="core-concepts-formula-and-cask">Core Concepts: formula and cask<a href="https://mikeq95blog.uk/en/blog/2026/05/28/homebrew-tutorials#core-concepts-formula-and-cask" class="hash-link" aria-label="Direct link to Core Concepts: formula and cask" title="Direct link to Core Concepts: formula and cask" translate="no">​</a></h2>
<p>Before using Homebrew, understand two key concepts:</p>
<ul>
<li class=""><strong>formula</strong>: installs <strong>command-line tools</strong> like <code>git</code> or <code>python</code> — no graphical interface</li>
<li class=""><strong>cask</strong>: installs <strong>GUI apps</strong> like Firefox or VS Code</li>
</ul>
<p>Simple rule: <strong>App with an icon → cask; command-line only → formula</strong>.</p>
<blockquote>
<p>Not talking about Gragas from League of Legends 😂</p>
</blockquote>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="installing-software">Installing Software<a href="https://mikeq95blog.uk/en/blog/2026/05/28/homebrew-tutorials#installing-software" class="hash-link" aria-label="Direct link to Installing Software" title="Direct link to Installing Software" translate="no">​</a></h2>
<p>Install a command-line tool (formula), e.g. git:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">brew install git</span><br></div></code></pre></div></div>
<p>Install a GUI app (cask), e.g. Firefox:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">brew install --cask firefox</span><br></div></code></pre></div></div>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="updating-software">Updating Software<a href="https://mikeq95blog.uk/en/blog/2026/05/28/homebrew-tutorials#updating-software" class="hash-link" aria-label="Direct link to Updating Software" title="Direct link to Updating Software" translate="no">​</a></h2>
<p>Before upgrading, refresh Homebrew's package list to get the latest versions:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">brew update  # refresh the package list (like refreshing the App Store)</span><br></div></code></pre></div></div>
<p>Then upgrade a specific package, e.g. Python:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">brew upgrade python</span><br></div></code></pre></div></div>
<blockquote>
<p><strong>Note:</strong> <code>brew update</code> updates Homebrew's own package index; <code>brew upgrade</code> actually upgrades the software. They are different.</p>
</blockquote>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="pinning-a-version">Pinning a Version<a href="https://mikeq95blog.uk/en/blog/2026/05/28/homebrew-tutorials#pinning-a-version" class="hash-link" aria-label="Direct link to Pinning a Version" title="Direct link to Pinning a Version" translate="no">​</a></h2>
<p>Sometimes you don't want a package to be auto-upgraded — for example, your project depends on a specific version of Python and upgrading would break things. Use <code>pin</code> to lock the version:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">brew pin python  # lock python, prevent auto-upgrade</span><br></div></code></pre></div></div>
<p>List pinned packages:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">brew list --pinned</span><br></div></code></pre></div></div>
<p>Unpin to allow upgrades again:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">brew unpin python</span><br></div></code></pre></div></div>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="uninstalling-software">Uninstalling Software<a href="https://mikeq95blog.uk/en/blog/2026/05/28/homebrew-tutorials#uninstalling-software" class="hash-link" aria-label="Direct link to Uninstalling Software" title="Direct link to Uninstalling Software" translate="no">​</a></h2>
<p>Uninstall a command-line tool:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">brew uninstall node</span><br></div></code></pre></div></div>
<p>Uninstall a GUI app:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">brew uninstall --cask firefox</span><br></div></code></pre></div></div>
<p>Uninstall Homebrew itself:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">/bin/bash -c "$(curl -fsSL https://gitee.com/ineo6/homebrew-install/raw/master/uninstall.sh)"</span><br></div></code></pre></div></div>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="summary">Summary<a href="https://mikeq95blog.uk/en/blog/2026/05/28/homebrew-tutorials#summary" class="hash-link" aria-label="Direct link to Summary" title="Direct link to Summary" translate="no">​</a></h2>
<table><thead><tr><th>Operation</th><th>Command</th></tr></thead><tbody><tr><td>Install CLI tool</td><td><code>brew install &lt;name&gt;</code></td></tr><tr><td>Install GUI app</td><td><code>brew install --cask &lt;name&gt;</code></td></tr><tr><td>Refresh package list</td><td><code>brew update</code></td></tr><tr><td>Upgrade software</td><td><code>brew upgrade &lt;name&gt;</code></td></tr><tr><td>Pin version</td><td><code>brew pin &lt;name&gt;</code></td></tr><tr><td>List pinned</td><td><code>brew list --pinned</code></td></tr><tr><td>Unpin version</td><td><code>brew unpin &lt;name&gt;</code></td></tr><tr><td>Uninstall</td><td><code>brew uninstall &lt;name&gt;</code></td></tr></tbody></table>
<p>These commands cover the vast majority of everyday Homebrew usage. In my opinion, Homebrew is an essential tool for every Mac — it's simply too convenient to go without.</p>]]></content>
        <category label="macOS" term="macOS"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Marker Tutorial]]></title>
        <id>https://mikeq95blog.uk/en/blog/2026/05/28/marker-github-project-tutorial</id>
        <link href="https://mikeq95blog.uk/en/blog/2026/05/28/marker-github-project-tutorial"/>
        <updated>2026-05-28T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Marker is an open-source tool that converts PDF, Word, PPT, and other file formats into Markdown. It's fast, and accuracy is pretty solid. This post documents how to get it running.]]></summary>
        <content type="html"><![CDATA[<p><a href="https://github.com/datalab-to/marker" target="_blank" rel="noopener noreferrer" class="">Marker</a> is an open-source tool that converts PDF, Word, PPT, and other file formats into Markdown. It's fast, and accuracy is pretty solid. This post documents how to get it running.</p>
<!-- -->
<hr>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="preface">Preface:<a href="https://mikeq95blog.uk/en/blog/2026/05/28/marker-github-project-tutorial#preface" class="hash-link" aria-label="Direct link to Preface:" title="Direct link to Preface:" translate="no">​</a></h3>
<p>I personally enjoy browsing <a href="https://www.instructables.com/" target="_blank" rel="noopener noreferrer" class="">instructables</a> — the site helpfully provides an "Export article as PDF" button in the top right, but no "Export as Markdown" option. I really wanted Markdown format, since AI tools prefer reading <code>.md</code> over PDF. After searching online, I found this GitHub project.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="setting-up-the-environment">Setting Up the Environment<a href="https://mikeq95blog.uk/en/blog/2026/05/28/marker-github-project-tutorial#setting-up-the-environment" class="hash-link" aria-label="Direct link to Setting Up the Environment" title="Direct link to Setting Up the Environment" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="prerequisites">Prerequisites<a href="https://mikeq95blog.uk/en/blog/2026/05/28/marker-github-project-tutorial#prerequisites" class="hash-link" aria-label="Direct link to Prerequisites" title="Direct link to Prerequisites" translate="no">​</a></h3>
<ul>
<li class="">Python 3.10 or higher</li>
<li class="">Conda is recommended for environment management (explained below)</li>
</ul>
<p>If you're on a Mac M1/M2/M3, no extra configuration is needed — PyTorch natively supports Apple Silicon.</p>
<hr>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="install-conda">Install Conda<a href="https://mikeq95blog.uk/en/blog/2026/05/28/marker-github-project-tutorial#install-conda" class="hash-link" aria-label="Direct link to Install Conda" title="Direct link to Install Conda" translate="no">​</a></h3>
<p>Miniforge is recommended: lightweight and well-supported on Apple Silicon.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain"># macOS Apple Silicon</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">curl -L -O https://github.com/conda-forge/miniforge/releases/latest/download/Miniforge3-MacOSX-arm64.sh</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">bash Miniforge3-MacOSX-arm64.sh</span><br></div></code></pre></div></div>
<p>After installation, run this command so Terminal recognizes conda:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">~/miniforge3/bin/conda init zsh</span><br></div></code></pre></div></div>
<p>Then close and reopen Terminal. You'll see <code>(base)</code> at the start of your prompt — conda is ready.</p>
<hr>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="create-a-virtual-environment">Create a Virtual Environment<a href="https://mikeq95blog.uk/en/blog/2026/05/28/marker-github-project-tutorial#create-a-virtual-environment" class="hash-link" aria-label="Direct link to Create a Virtual Environment" title="Direct link to Create a Virtual Environment" translate="no">​</a></h3>
<p>Think of a virtual environment as a separate "room" for this project — packages installed here won't affect anything else on your system.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">conda create -n marker python=3.11 -y</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">conda activate marker</span><br></div></code></pre></div></div>
<p>Once activated, your prompt changes from <code>(base)</code> to <code>(marker)</code>.</p>
<hr>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="install-marker">Install Marker<a href="https://mikeq95blog.uk/en/blog/2026/05/28/marker-github-project-tutorial#install-marker" class="hash-link" aria-label="Direct link to Install Marker" title="Direct link to Install Marker" translate="no">​</a></h3>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">pip install marker-pdf</span><br></div></code></pre></div></div>
<p>If you also need to convert Word, PPT, or EPUB files:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">pip install marker-pdf[full]</span><br></div></code></pre></div></div>
<hr>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="verify-installation">Verify Installation<a href="https://mikeq95blog.uk/en/blog/2026/05/28/marker-github-project-tutorial#verify-installation" class="hash-link" aria-label="Direct link to Verify Installation" title="Direct link to Verify Installation" translate="no">​</a></h3>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">marker_single --help</span><br></div></code></pre></div></div>
<p>Wait about 10–15 seconds. If a list of parameters is printed, you're good to go.</p>
<hr>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="activating-the-environment-each-session">Activating the Environment Each Session<a href="https://mikeq95blog.uk/en/blog/2026/05/28/marker-github-project-tutorial#activating-the-environment-each-session" class="hash-link" aria-label="Direct link to Activating the Environment Each Session" title="Direct link to Activating the Environment Each Session" translate="no">​</a></h3>
<p>Every time you open a new Terminal, remember to activate the environment first:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">conda activate marker</span><br></div></code></pre></div></div>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="how-to-use">How to Use<a href="https://mikeq95blog.uk/en/blog/2026/05/28/marker-github-project-tutorial#how-to-use" class="hash-link" aria-label="Direct link to How to Use" title="Direct link to How to Use" translate="no">​</a></h2>
<p>The basic format is a single line:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">marker_single /path/to/your/file --output_dir /output/directory</span><br></div></code></pre></div></div>
<p>Useful options:</p>
<ul>
<li class=""><code>--output_dir</code>: specify the output folder</li>
<li class=""><code>--output_format</code>: output format — <code>markdown</code>, <code>json</code>, or <code>html</code></li>
<li class=""><code>--page_range</code>: convert specific pages, e.g. <code>"0,5-10"</code> (pages are 0-indexed)</li>
<li class=""><code>--force_ocr</code>: force OCR — use this when text in the PDF is actually an image</li>
<li class=""><code>--langs zh</code>: tells Marker the document is in Chinese for better accuracy</li>
<li class=""><code>--use_llm</code>: use an LLM for assistance — higher accuracy, requires an API key</li>
</ul>
<p>After conversion, the output folder will contain a <code>.md</code> file and extracted images. Open with Typora or Obsidian for proper rendering.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="practical-examples">Practical Examples<a href="https://mikeq95blog.uk/en/blog/2026/05/28/marker-github-project-tutorial#practical-examples" class="hash-link" aria-label="Direct link to Practical Examples" title="Direct link to Practical Examples" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="convert-a-research-paper">Convert a Research Paper<a href="https://mikeq95blog.uk/en/blog/2026/05/28/marker-github-project-tutorial#convert-a-research-paper" class="hash-link" aria-label="Direct link to Convert a Research Paper" title="Direct link to Convert a Research Paper" translate="no">​</a></h3>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">marker_single ~/Downloads/paper.pdf \</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  --output_dir ~/Documents/notes</span><br></div></code></pre></div></div>
<p>The first run downloads the AI models (~1 GB) — be patient. Afterwards, math formulas are converted to LaTeX, tables and headings are preserved. Results are quite good.</p>
<hr>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="let-ai-tools-handle-the-deployment">Let AI Tools Handle the Deployment<a href="https://mikeq95blog.uk/en/blog/2026/05/28/marker-github-project-tutorial#let-ai-tools-handle-the-deployment" class="hash-link" aria-label="Direct link to Let AI Tools Handle the Deployment" title="Direct link to Let AI Tools Handle the Deployment" translate="no">​</a></h2>
<p>If the steps above feel tedious, paste this prompt into Claude Code, Cursor, or a similar AI tool and let it set up the environment automatically.</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">You are a professional Python environment configuration engineer. Please fully deploy the marker-pdf runtime environment on this machine.</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">My setup: macOS Apple Silicon (M1 Pro), shell is zsh, Conda is installed at ~/miniforge3.</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">Please complete the following steps in order, check the result after each step, and immediately diagnose and fix any errors:</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">1. Check if conda is available (conda --version). If not, run ~/miniforge3/bin/conda init zsh and remind me to reopen Terminal.</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">2. Create and activate a virtual environment: conda create -n marker python=3.11 -y &amp;&amp; conda activate marker</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">3. Install marker: pip install marker-pdf</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">4. Verify PyTorch: python -c "import torch; print(torch.__version__)". If you see a libtorch_cpu.dylib error, reinstall immediately: pip uninstall torch torchvision torchaudio -y &amp;&amp; pip install torch torchvision torchaudio</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">5. Verify marker: run marker_single --help, wait ~20 seconds. A list of parameters means success.</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">Tell me what you're doing before each step. Do not modify system-level configuration. When done, output the installed versions of Python, PyTorch, and marker-pdf.</span><br></div></code></pre></div></div>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="uninstalling">Uninstalling<a href="https://mikeq95blog.uk/en/blog/2026/05/28/marker-github-project-tutorial#uninstalling" class="hash-link" aria-label="Direct link to Uninstalling" title="Direct link to Uninstalling" translate="no">​</a></h2>
<p>Uninstall only the marker package, keep the environment:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">conda activate marker</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">pip uninstall marker-pdf</span><br></div></code></pre></div></div>
<p>Delete the entire environment (more thorough):</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">conda deactivate</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">conda env remove -n marker</span><br></div></code></pre></div></div>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="troubleshooting">Troubleshooting<a href="https://mikeq95blog.uk/en/blog/2026/05/28/marker-github-project-tutorial#troubleshooting" class="hash-link" aria-label="Direct link to Troubleshooting" title="Direct link to Troubleshooting" translate="no">​</a></h2>
<p><strong>Terminal is stuck?</strong> The first run downloads models, which can be slow on some networks. Try configuring a proxy for Terminal:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">export https_proxy=http://127.0.0.1:YOUR_PORT</span><br></div></code></pre></div></div>
<p><strong><code>libtorch_cpu.dylib</code> error on Mac?</strong> Reinstall PyTorch:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">pip uninstall torch torchvision torchaudio -y</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">pip install torch torchvision torchaudio</span><br></div></code></pre></div></div>
<p><strong>Poor Chinese recognition?</strong> Add <code>--langs zh</code>. For scanned documents, also add <code>--force_ocr</code>.</p>
<p><strong><code>command not found</code>?</strong> The environment isn't activated. Run <code>conda activate marker</code> first.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="summary">Summary<a href="https://mikeq95blog.uk/en/blog/2026/05/28/marker-github-project-tutorial#summary" class="hash-link" aria-label="Direct link to Summary" title="Direct link to Summary" translate="no">​</a></h2>
<p>Marker is essentially a <strong>locally-running document parsing engine</strong>, powered by AI models specifically trained on document layouts — not a general-purpose LLM. This makes it fast, offline-capable, and effective without any API key. It excels at complex academic PDFs: converting math formulas to LaTeX, preserving table structure, and extracting images separately. If you need to organize large volumes of documents into a knowledge base, or want to feed PDF content into an LLM for further processing, Marker is one of the best open-source options available.</p>
<hr>
<p><em>Based on <a href="https://github.com/datalab-to/marker" target="_blank" rel="noopener noreferrer" class="">datalab-to/marker</a>, compatible with marker v1.x</em></p>]]></content>
        <category label="GitHub" term="GitHub"/>
        <category label="macOS" term="macOS"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[My Favorite Songs (Jay Chou)]]></title>
        <id>https://mikeq95blog.uk/en/blog/2026/05/24/my-favorite-songs</id>
        <link href="https://mikeq95blog.uk/en/blog/2026/05/24/my-favorite-songs"/>
        <updated>2026-05-24T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Jay Chou's classic songs have accompanied me throughout my youth. Here are some of my favorites:]]></summary>
        <content type="html"><![CDATA[<p>Jay Chou's classic songs have accompanied me throughout my youth. Here are some of my favorites:</p>
<!-- -->
<ol>
<li class=""><strong>Qi Li Xiang (Seven-Mile Fragrance)</strong> - A timeless melody with the taste of summer.</li>
<li class=""><strong>Ye Qu (Nocturne)</strong> - The moment that intro plays, memories come flooding back.</li>
<li class=""><strong>Qing Tian (Clear Sky)</strong> - The secret crush and regret of adolescence.</li>
<li class=""><strong>Yi Fu Zhi Ming (In the Name of the Father)</strong> - The pinnacle of his dark style.</li>
<li class=""><strong>Qing Hua Ci (Blue and White Porcelain)</strong> - A beautiful ode to Chinese aesthetics.</li>
</ol>
<p>These songs are more than just melodies — they are the mark of time.</p>
<hr>
<p>Want to listen? Click below to open the player. You can upload local audio files and <code>.lrc</code> lyrics files to enjoy Apple Music-style scrolling lyrics.</p>
<a href="https://mikeq95blog.uk/en/music-player" target="_blank" rel="noopener noreferrer" style="display:flex;align-items:center;gap:12px;padding:16px 20px;border-radius:12px;border:1px solid var(--ifm-color-emphasis-300);text-decoration:none;color:inherit;margin-top:12px;transition:box-shadow 0.2s"><span style="font-size:32px">🎵</span><div><div style="font-weight:bold;font-size:16px">Open Music Player</div><div style="font-size:13px;color:var(--ifm-color-emphasis-500);margin-top:2px">Scrolling Lyrics · Apple Music Style · Opens in New Tab</div></div><span style="margin-left:auto;font-size:20px;color:var(--ifm-color-emphasis-400)">↗</span></a>]]></content>
        <category label="Music" term="Music"/>
        <category label="Jay Chou" term="Jay Chou"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[🌐 macOS Network Reset Commands — Quick Reference]]></title>
        <id>https://mikeq95blog.uk/en/blog/2025/05/16/quick-reference-for-macOS network-reset-commands</id>
        <link href="https://mikeq95blog.uk/en/blog/2025/05/16/quick-reference-for-macOS network-reset-commands"/>
        <updated>2026-05-16T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[In most cases, running DNS flush + DHCP reset is enough to fix the majority of network issues.]]></summary>
        <content type="html"><![CDATA[<blockquote>
<p>In most cases, running <strong>DNS flush + DHCP reset</strong> is enough to fix the majority of network issues.</p>
</blockquote>
<!-- -->
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="common-commands-in-recommended-order">Common Commands (in recommended order)<a href="https://mikeq95blog.uk/en/blog/2025/05/16/quick-reference-for-macOS%20network-reset-commands#common-commands-in-recommended-order" class="hash-link" aria-label="Direct link to Common Commands (in recommended order)" title="Direct link to Common Commands (in recommended order)" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="1-flush-dns-cache">1. Flush DNS Cache<a href="https://mikeq95blog.uk/en/blog/2025/05/16/quick-reference-for-macOS%20network-reset-commands#1-flush-dns-cache" class="hash-link" aria-label="Direct link to 1. Flush DNS Cache" title="Direct link to 1. Flush DNS Cache" translate="no">​</a></h3>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">sudo dscacheutil -flushcache; sudo killall -HUP mDNSResponder</span><br></div></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="2-release-and-renew-ip-address-dhcp">2. Release and Renew IP Address (DHCP)<a href="https://mikeq95blog.uk/en/blog/2025/05/16/quick-reference-for-macOS%20network-reset-commands#2-release-and-renew-ip-address-dhcp" class="hash-link" aria-label="Direct link to 2. Release and Renew IP Address (DHCP)" title="Direct link to 2. Release and Renew IP Address (DHCP)" translate="no">​</a></h3>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">sudo ipconfig set en0 DHCP</span><br></div></code></pre></div></div>]]></content>
        <category label="macOS" term="macOS"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Search Engine User Guide]]></title>
        <id>https://mikeq95blog.uk/en/blog/2026/05/16/recommended-commonly-used-search-engines</id>
        <link href="https://mikeq95blog.uk/en/blog/2026/05/16/recommended-commonly-used-search-engines"/>
        <updated>2026-05-16T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[1. Choosing a Search Engine]]></summary>
        <content type="html"><![CDATA[<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="1-choosing-a-search-engine">1. Choosing a Search Engine<a href="https://mikeq95blog.uk/en/blog/2026/05/16/recommended-commonly-used-search-engines#1-choosing-a-search-engine" class="hash-link" aria-label="Direct link to 1. Choosing a Search Engine" title="Direct link to 1. Choosing a Search Engine" translate="no">​</a></h3>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="recommended-order">Recommended Order<a href="https://mikeq95blog.uk/en/blog/2026/05/16/recommended-commonly-used-search-engines#recommended-order" class="hash-link" aria-label="Direct link to Recommended Order" title="Direct link to Recommended Order" translate="no">​</a></h4>
<p>Google is great for everyday searches. DuckDuckGo and Brave are better for privacy-conscious users. Yandex is good for finding edgier content. Bing (Chinese version) works as a fallback if you can't access international sites.</p>
<!-- -->
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="engine-characteristics">Engine Characteristics<a href="https://mikeq95blog.uk/en/blog/2026/05/16/recommended-commonly-used-search-engines#engine-characteristics" class="hash-link" aria-label="Direct link to Engine Characteristics" title="Direct link to Engine Characteristics" translate="no">​</a></h4>
<ul>
<li class=""><strong>Google</strong>: Results for controversial content lean toward mainstream PC viewpoints; opposing views are sparse and weak.</li>
<li class=""><strong>DuckDuckGo</strong>: More neutral than Google, but search keywords aren't highlighted in results — you'll need a userscript to fix that (see end of post). (Any AI can write the script for you.)</li>
<li class=""><strong>Yandex</strong>: Completely ignores Western political correctness; good for sensitive or edgy content.<!-- -->
<ul>
<li class="">e.g. Search "Epstein list" — only Yandex puts the actual list at the top</li>
<li class="">e.g. Search "Hollywood scandals" — only Yandex shows hard-hitting results</li>
</ul>
</li>
<li class=""><strong>Political correctness level</strong>: <code>Google &gt; Brave &gt; DuckDuckGo &gt; Yandex</code></li>
</ul>
<hr>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="2-practical-search-tips">2. Practical Search Tips<a href="https://mikeq95blog.uk/en/blog/2026/05/16/recommended-commonly-used-search-engines#2-practical-search-tips" class="hash-link" aria-label="Direct link to 2. Practical Search Tips" title="Direct link to 2. Practical Search Tips" translate="no">​</a></h3>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="software-resources--free-music-downloads">Software Resources &amp; Free Music Downloads<a href="https://mikeq95blog.uk/en/blog/2026/05/16/recommended-commonly-used-search-engines#software-resources--free-music-downloads" class="hash-link" aria-label="Direct link to Software Resources &amp; Free Music Downloads" title="Direct link to Software Resources &amp; Free Music Downloads" translate="no">​</a></h4>
<p>Use <strong>Yandex</strong> and search:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">software name + cracked / premium / unlocked / Скачать</span><br></div></code></pre></div></div>
<p>Look for results with Russian-language links — they usually allow direct download.
Works for Android, PC, and Mac.</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="finding-e-books-annas-archive--z-library">Finding E-books (Anna's Archive / Z-Library)<a href="https://mikeq95blog.uk/en/blog/2026/05/16/recommended-commonly-used-search-engines#finding-e-books-annas-archive--z-library" class="hash-link" aria-label="Direct link to Finding E-books (Anna's Archive / Z-Library)" title="Direct link to Finding E-books (Anna's Archive / Z-Library)" translate="no">​</a></h4>
<blockquote>
<p>Quick tip: if you Google "Anna's Archive" or "Z-Library", you'll likely get a bunch of unrelated results. Try Yandex instead — the first result is almost always what you're looking for. (Yandex is genuinely underrated!)</p>
</blockquote>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">keyword + edition      </span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">keyword + translation  </span><br></div></code></pre></div></div>
<hr>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="3-duckduckgo-keyword-highlight-userscript">3. DuckDuckGo Keyword Highlight Userscript<a href="https://mikeq95blog.uk/en/blog/2026/05/16/recommended-commonly-used-search-engines#3-duckduckgo-keyword-highlight-userscript" class="hash-link" aria-label="Direct link to 3. DuckDuckGo Keyword Highlight Userscript" title="Direct link to 3. DuckDuckGo Keyword Highlight Userscript" translate="no">​</a></h3>
<blockquote>
<p>Requires the <a href="https://www.tampermonkey.net/" target="_blank" rel="noopener noreferrer" class="">Tampermonkey</a> browser extension.</p>
</blockquote>
<p>javascript</p>
<div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">// ==UserScript==</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">// @name         DuckDuckGo Search Keyword Highlight</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">// @namespace    http://tampermonkey.net/</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">// @version      2025-08-05</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">// @description  Highlights search keywords in DuckDuckGo results</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">// @author       You</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">// @match        https://duckduckgo.com/?*</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">// @grant        GM_addStyle</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">// ==/UserScript==</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">function</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token string" style="color:#e3116c">'use strict'</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token function maybe-class-name" style="color:#d73a49">GM_addStyle</span><span class="token punctuation" style="color:#393A34">(</span><span class="token template-string template-punctuation string" style="color:#e3116c">`</span><span class="token template-string string" style="color:#e3116c"></span><br></div><div class="token-line" style="color:#393A34"><span class="token template-string string" style="color:#e3116c">        .kY2IgmnCmOGjharHErah span b {</span><br></div><div class="token-line" style="color:#393A34"><span class="token template-string string" style="color:#e3116c">            color: #ff897e !important;</span><br></div><div class="token-line" style="color:#393A34"><span class="token template-string string" style="color:#e3116c">        }</span><br></div><div class="token-line" style="color:#393A34"><span class="token template-string string" style="color:#e3116c">    </span><span class="token template-string template-punctuation string" style="color:#e3116c">`</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></div></code></pre></div></div>
<hr>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="4-faq">4. FAQ<a href="https://mikeq95blog.uk/en/blog/2026/05/16/recommended-commonly-used-search-engines#4-faq" class="hash-link" aria-label="Direct link to 4. FAQ" title="Direct link to 4. FAQ" translate="no">​</a></h3>
<ol>
<li class=""><strong>I searched the way you described but got no results — why?</strong>
Search engines use safe mode by default. Go to Settings and turn it off — look for "No filter" (filter = content filtering; no filter = uncensored results). That's the one you want.</li>
</ol>]]></content>
        <category label="Collection" term="Collection"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Convert Articles to Podcast Audio with Kokoro]]></title>
        <id>https://mikeq95blog.uk/en/blog/2026/05/16/kokoro-tts-tutorial</id>
        <link href="https://mikeq95blog.uk/en/blog/2026/05/16/kokoro-tts-tutorial"/>
        <updated>2026-05-16T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[I wanted to convert my English articles into audio so I could listen while walking. After looking around, the only option that's free, sounds good, and runs locally is Kokoro.]]></summary>
        <content type="html"><![CDATA[<p>I wanted to convert my English articles into audio so I could listen while walking. After looking around, the only option that's free, sounds good, and runs locally is <a href="https://github.com/hexgrad/kokoro" target="_blank" rel="noopener noreferrer" class="">Kokoro</a>.</p>
<!-- -->
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-is-kokoro">What Is Kokoro<a href="https://mikeq95blog.uk/en/blog/2026/05/16/kokoro-tts-tutorial#what-is-kokoro" class="hash-link" aria-label="Direct link to What Is Kokoro" title="Direct link to What Is Kokoro" translate="no">​</a></h2>
<p>Kokoro is an open-source TTS (text-to-speech) model with 82M parameters — lightweight but surprisingly good. English quality approaches ElevenLabs commercial level, with 88 voices to choose from and an Apache 2.0 license, free for commercial use.</p>
<p>We'll use <a href="https://github.com/eduardolat/kokoro-web" target="_blank" rel="noopener noreferrer" class="">kokoro-web</a> — a project that wraps Kokoro into a local service, launched with a single Docker command, with a web UI included, ready to use out of the box.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="choosing-a-voice">Choosing a Voice<a href="https://mikeq95blog.uk/en/blog/2026/05/16/kokoro-tts-tutorial#choosing-a-voice" class="hash-link" aria-label="Direct link to Choosing a Voice" title="Direct link to Choosing a Voice" translate="no">​</a></h2>
<p>Kokoro voices are graded A–D by quality, A being highest. For English, just pick from these:</p>
<table><thead><tr><th>Voice</th><th>Grade</th><th>Style</th></tr></thead><tbody><tr><td>Heart</td><td>A</td><td>Warm female voice, top pick</td></tr><tr><td>Bella</td><td>A-</td><td>High-quality female voice</td></tr><tr><td>Michael</td><td>C+</td><td>Mature male voice</td></tr><tr><td>Emma</td><td>B-</td><td>British female voice</td></tr></tbody></table>
<blockquote>
<p>The first time you use a voice, its model file is downloaded automatically and cached — no need to re-download.</p>
</blockquote>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="installing-docker">Installing Docker<a href="https://mikeq95blog.uk/en/blog/2026/05/16/kokoro-tts-tutorial#installing-docker" class="hash-link" aria-label="Direct link to Installing Docker" title="Direct link to Installing Docker" translate="no">​</a></h2>
<p>If you don't have Docker yet, install it first.</p>
<p><strong>International network</strong>: download from the official site: <a href="https://www.docker.com/products/docker-desktop/" target="_blank" rel="noopener noreferrer" class="">docker.com/products/docker-desktop</a></p>
<p><strong>Chinese network</strong>: the official site can be slow, use Aliyun's mirror:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">https://mirrors.aliyun.com/docker-toolbox/mac/docker-for-mac/</span><br></div></code></pre></div></div>
<p>Download the <code>.dmg</code>, double-click to install, open Docker Desktop, and wait for the 🐳 icon to appear in the menu bar.</p>
<p>Then configure the command-line path so Terminal can find the docker command:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">echo 'export PATH="$PATH:/Applications/Docker.app/Contents/Resources/bin"' &gt;&gt; ~/.zshrc</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">source ~/.zshrc</span><br></div></code></pre></div></div>
<p>Verify the installation:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">docker --version &amp;&amp; docker compose version</span><br></div></code></pre></div></div>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="deploying-kokoro-web">Deploying kokoro-web<a href="https://mikeq95blog.uk/en/blog/2026/05/16/kokoro-tts-tutorial#deploying-kokoro-web" class="hash-link" aria-label="Direct link to Deploying kokoro-web" title="Direct link to Deploying kokoro-web" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="1-create-a-project-directory">1. Create a project directory<a href="https://mikeq95blog.uk/en/blog/2026/05/16/kokoro-tts-tutorial#1-create-a-project-directory" class="hash-link" aria-label="Direct link to 1. Create a project directory" title="Direct link to 1. Create a project directory" translate="no">​</a></h3>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">mkdir kokoro-web &amp;&amp; cd kokoro-web</span><br></div></code></pre></div></div>
<blockquote>
<p><strong>Make sure you <code>cd</code> into the folder before doing anything else.</strong> The <code>docker compose</code> commands must run inside this directory, otherwise you'll get <code>no configuration file provided</code>.</p>
</blockquote>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="2-create-the-config-file">2. Create the config file<a href="https://mikeq95blog.uk/en/blog/2026/05/16/kokoro-tts-tutorial#2-create-the-config-file" class="hash-link" aria-label="Direct link to 2. Create the config file" title="Direct link to 2. Create the config file" translate="no">​</a></h3>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">cat &gt; compose.yaml &lt;&lt; 'EOF'</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">services:</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  kokoro-web:</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    image: ghcr.io/eduardolat/kokoro-web:latest</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    ports:</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      - "3000:3000"</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    environment:</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      - KW_SECRET_API_KEY=my-secret-key</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    volumes:</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      - ./kokoro-cache:/kokoro/cache</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    restart: unless-stopped</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">EOF</span><br></div></code></pre></div></div>
<p><code>KW_SECRET_API_KEY</code> is the access password for the local service — for local use, anything works, just remember what you set. I'd suggest leaving it as the default.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="3-start-the-service">3. Start the service<a href="https://mikeq95blog.uk/en/blog/2026/05/16/kokoro-tts-tutorial#3-start-the-service" class="hash-link" aria-label="Direct link to 3. Start the service" title="Direct link to 3. Start the service" translate="no">​</a></h3>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">docker compose up -d</span><br></div></code></pre></div></div>
<p>The first start pulls the image, which can be slow on some networks — be patient.</p>
<p>Once you see this, it's up:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">docker compose logs -f</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"># Success: Listening on http://0.0.0.0:3000</span><br></div></code></pre></div></div>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="using-the-web-ui">Using the Web UI<a href="https://mikeq95blog.uk/en/blog/2026/05/16/kokoro-tts-tutorial#using-the-web-ui" class="hash-link" aria-label="Direct link to Using the Web UI" title="Direct link to Using the Web UI" translate="no">​</a></h2>
<p>Open your browser and go to <code>http://localhost:3000</code>.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="configure-the-api-important">Configure the API (important)<a href="https://mikeq95blog.uk/en/blog/2026/05/16/kokoro-tts-tutorial#configure-the-api-important" class="hash-link" aria-label="Direct link to Configure the API (important)" title="Direct link to Configure the API (important)" translate="no">​</a></h3>
<p>Click <strong>API Settings</strong> in the top right corner:</p>
<ul>
<li class=""><strong>Base URL</strong>: <code>http://localhost:3000/api/v1</code> (default, no change needed)</li>
<li class=""><strong>API Key</strong>: <code>my-secret-key</code></li>
</ul>
<blockquote>
<p><strong>Gotcha</strong>: the API Key is just the value itself — don't include the <code>- KW_SECRET_API_KEY=</code> prefix from the compose file.</p>
</blockquote>
<p>Click <strong>OK</strong>.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="generation-settings">Generation Settings<a href="https://mikeq95blog.uk/en/blog/2026/05/16/kokoro-tts-tutorial#generation-settings" class="hash-link" aria-label="Direct link to Generation Settings" title="Direct link to Generation Settings" translate="no">​</a></h3>
<p>Back on the main screen, a few key options:</p>
<table><thead><tr><th>Option</th><th>Recommended</th><th>Notes</th></tr></thead><tbody><tr><td><strong>Execution place</strong></td><td><code>API (Self-hosted)</code></td><td>Use local Docker, not Browser</td></tr><tr><td><strong>Model quantization</strong></td><td><code>q8f16</code></td><td>Best balance of speed and quality</td></tr><tr><td><strong>Language accent</strong></td><td><code>English (US)</code></td><td>For English content</td></tr><tr><td><strong>Voice</strong></td><td><code>Heart</code></td><td>Top recommendation</td></tr></tbody></table>
<p><strong>Always set Execution place to <code>API (Self-hosted)</code>.</strong> Running in the browser runs the model in your browser — much slower and re-downloads every time.</p>
<p>Paste your article into <strong>Text to process</strong>, then click <strong>Generate</strong>.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="demo">Demo<a href="https://mikeq95blog.uk/en/blog/2026/05/16/kokoro-tts-tutorial#demo" class="hash-link" aria-label="Direct link to Demo" title="Direct link to Demo" translate="no">​</a></h3>
<p>Input text:</p>
<blockquote>
<p>Google is renowned for its innovative and employee-centric work environment. The company's campuses, often called "Googleplexes," feature vibrant designs with open spaces, recreational facilities, free gourmet meals, and wellness centers. Employees enjoy flexible work hours, remote options, and a strong emphasis on collaboration through team projects and hackathons.</p>
<p>A culture of creativity thrives with "20% time," encouraging personal passion projects that have led to major products like Gmail. Diversity, inclusion, and continuous learning are prioritized through training programs and supportive leadership. This unique blend of fun, freedom, and purpose fosters high productivity and job satisfaction, making Google a top destination for tech talent worldwide.</p>
</blockquote>
<p>Generated with the Heart voice (~150 words, ~30 seconds on local CPU):</p>
<audio controls=""><source src="/assets/kokoro-demo-google.mp3" type="audio/mpeg"></audio>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="processing-markdown-files">Processing Markdown Files<a href="https://mikeq95blog.uk/en/blog/2026/05/16/kokoro-tts-tutorial#processing-markdown-files" class="hash-link" aria-label="Direct link to Processing Markdown Files" title="Direct link to Processing Markdown Files" translate="no">​</a></h2>
<p>Kokoro only accepts plain text. Pasting a <code>.md</code> file directly will cause it to read out <code>##</code>, <code>**bold**</code>, and other Markdown syntax aloud.</p>
<p>Use <code>pandoc</code> to convert first:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain"># Install pandoc</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">brew install pandoc</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"># Convert md to plain text, then copy-paste the output</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">pandoc article.md -t plain</span><br></div></code></pre></div></div>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="useful-commands">Useful Commands<a href="https://mikeq95blog.uk/en/blog/2026/05/16/kokoro-tts-tutorial#useful-commands" class="hash-link" aria-label="Direct link to Useful Commands" title="Direct link to Useful Commands" translate="no">​</a></h2>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">docker compose logs -f    # view live logs</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">docker compose stop       # stop the service</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">docker compose start      # start the service</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">docker compose pull       # update to the latest version</span><br></div></code></pre></div></div>
<hr>
<p><em>Environment: MacBook Pro M1 Pro · macOS · Docker Desktop 29.4.3</em></p>]]></content>
        <category label="GitHub" term="GitHub"/>
        <category label="macOS" term="macOS"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Programming English Vocabulary Collection]]></title>
        <id>https://mikeq95blog.uk/en/blog/2026/04/29/coding-english-vocabulary</id>
        <link href="https://mikeq95blog.uk/en/blog/2026/04/29/coding-english-vocabulary"/>
        <updated>2026-04-29T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[1. demonstrate]]></summary>
        <content type="html"><![CDATA[<ol>
<li class="">
<p><strong>demonstrate</strong></p>
<ul>
<li class="">Example: This tutorial no longer ==demonstrates== current SwiftUI or Xcode practices.</li>
<li class="">Meaning: to show or illustrate something; to demonstrate</li>
</ul>
</li>
</ol>
<!-- -->
<ol start="2">
<li class="">
<p><strong>prevent</strong></p>
<ul>
<li class="">Example: This option will ==prevent== Shadowrocket from being set as the default route.</li>
<li class="">Meaning: to stop something from happening; to block</li>
</ul>
</li>
<li class="">
<p><strong>modifier</strong></p>
<ul>
<li class="">Example: A new ==modifier== creates a new view based on the original one.</li>
<li class="">Meaning: (in SwiftUI) a method that transforms or configures a view</li>
</ul>
</li>
<li class="">
<p><strong>components</strong></p>
<ul>
<li class="">Example: One of the most common and recognizable user interface ==components== is the combination of an icon and a label.</li>
<li class="">Meaning: individual parts or elements that make up a larger system; components</li>
</ul>
</li>
<li class="">
<p><strong>idiom</strong></p>
<ul>
<li class="">Example: This ==idiom== appears across many kinds of apps and shows up in collections, lists, menus of action items, and disclosable lists, just to name a few.</li>
<li class="">Meaning: a common pattern or convention in UI/programming; an established way of doing something</li>
</ul>
</li>
<li class="">
<p><strong>just to name a few</strong></p>
<ul>
<li class="">Example: This idiom appears across many kinds of apps and shows up in collections, lists, menus of action items, and disclosable lists, ==just to name a few==.</li>
<li class="">Meaning: used to indicate that only a small number of examples are being given; "among others"</li>
</ul>
</li>
<li class="">
<p><strong>interface</strong></p>
<ul>
<li class="">Example: You create the user ==interface==, or UI, for your app inside the body; the entire contents of your app are in the code below.</li>
<li class="">Meaning: the visual layer of an application that users interact with; user interface (UI)</li>
</ul>
</li>
</ol>
<div class="language-swift codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-swift codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">// NOTE: - Demo code</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> </span><span class="token class-name">SwiftUI</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">struct</span><span class="token plain"> </span><span class="token class-name">ContentView</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token class-name">View</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">var</span><span class="token plain"> body</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">some</span><span class="token plain"> </span><span class="token class-name">View</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">VStack</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token class-name">Image</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">systemName</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string-literal string" style="color:#e3116c">"globe"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">imageScale</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">large</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">foregroundColor</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">tint</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token class-name">Text</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string-literal string" style="color:#e3116c">"Hello World"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token other-directive property" style="color:#36acaa">#Preview</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token class-name">ContentView</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div>
<ol start="8">
<li class="">
<p><strong>instance</strong></p>
<ul>
<li class="">Example: To construct your narrative, the app needs an ==instance== of Story, which takes an array of StoryPage instances.</li>
<li class="">Meaning: a specific occurrence of an object created from a class or struct</li>
</ul>
</li>
<li class="">
<p><strong>hold</strong></p>
<ul>
<li class="">Example: The text property ==holds== a String that describes the choice readers can make.</li>
<li class="">Meaning: to store or contain a value; to hold</li>
</ul>
</li>
<li class="">
<p><strong>present</strong></p>
<ul>
<li class="">Example: Use a navigation stack to ==present== a stack of views over a root view.</li>
<li class="">Meaning: to display or show a view on screen</li>
</ul>
</li>
<li class="">
<p><strong>indicates</strong></p>
<ul>
<li class="">Example: A value-destination ==indicates== that you are pushing a value onto the path.</li>
<li class="">Meaning: to signal or show that something is the case; to indicate</li>
</ul>
</li>
</ol>]]></content>
        <category label="English" term="English"/>
        <category label="Swift" term="Swift"/>
        <category label="Collection" term="Collection"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[General English Vocabulary Collection]]></title>
        <id>https://mikeq95blog.uk/en/blog/2026/04/29/general-english-vocabulary</id>
        <link href="https://mikeq95blog.uk/en/blog/2026/04/29/general-english-vocabulary"/>
        <updated>2026-04-29T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[1. Based on the principle of voluntariness]]></summary>
        <content type="html"><![CDATA[<ol>
<li class="">
<p><strong>Based on the principle of voluntariness</strong></p>
<ul>
<li class="">Example: Membership in the union is ==based on the principle of voluntariness==—no employee is forced to join.</li>
<li class="">Meaning: following the principle that participation is entirely a personal choice; voluntary basis</li>
</ul>
</li>
</ol>
<!-- -->
<ol start="2">
<li class="">
<p><strong>One for all, all for one</strong></p>
<ul>
<li class="">Example: The three friends made a pact: ==one for all, all for one==. They promised to stand by each other no matter what challenges lay ahead.</li>
<li class="">Meaning: a phrase expressing mutual support and solidarity within a group</li>
</ul>
</li>
<li class="">
<p><strong>Be careful, though</strong></p>
<ul>
<li class="">Example: The restaurant is amazing and cheap. ==Be careful==, though: it gets really crowded on weekends.</li>
<li class="">Meaning: used to add a warning or caveat after a positive statement; "that said, watch out for..."</li>
</ul>
</li>
<li class="">
<p><strong>embedded in</strong></p>
<ul>
<li class="">Example: These attitudes are ==embedded in== our society.</li>
<li class="">Meaning: deeply ingrained or firmly fixed within something; deeply rooted in</li>
</ul>
</li>
<li class="">
<p><strong>enthusiasts</strong></p>
<ul>
<li class="">Example: She is one of the most dedicated fitness ==enthusiasts== I have ever met.</li>
<li class="">Meaning: people who are highly interested in and passionate about a particular activity or subject</li>
</ul>
</li>
</ol>]]></content>
        <category label="English" term="English"/>
        <category label="Collection" term="Collection"/>
    </entry>
</feed>