<?xml version="1.0" encoding="UTF-8" standalone="no"?><rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" version="2.0">

<channel>
	<title>Jesse Liberty - Silverlight Geek</title>
	<atom:link href="https://jesseliberty.com/feed/" rel="self" type="application/rss+xml"/>
	<link>https://jesseliberty.com</link>
	<description>More Signal - Less Noise</description>
	<lastBuildDate>Sat, 04 Apr 2026 11:02:54 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.4</generator>
	<item>
		<title>Microsoft Agent Framework – Part 0</title>
		<link>https://jesseliberty.com/2026/04/04/microsoft-agent-framework/</link>
		
		<dc:creator><![CDATA[Jesse Liberty]]></dc:creator>
		<pubDate>Sat, 04 Apr 2026 11:01:58 +0000</pubDate>
				<category><![CDATA[Essentials]]></category>
		<guid isPermaLink="false">https://jesseliberty.com/?p=13227</guid>

					<description><![CDATA[I&#8217;ve been looking at a number of different ways to build Agents. I&#8217;ve settled on two and will be documenting what I learn as I go: The advantage of the first is that you understand the underlying mechanisms in more &#8230; <a href="https://jesseliberty.com/2026/04/04/microsoft-agent-framework/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
										<content:encoded><![CDATA[
<p>I&#8217;ve been looking at a number of different ways to build Agents. I&#8217;ve settled on two and will be documenting what I learn as I go:</p>



<ul class="wp-block-list">
<li>Building from first principles based on my course on Agentics at Johns Hopkins</li>



<li>Building using Microsoft&#8217;s new Agent Framework</li>



<li></li>
</ul>



<figure class="wp-block-image size-large is-resized"><img fetchpriority="high" decoding="async" width="800" height="446" src="https://jesseliberty.com/wp-content/uploads/2026/04/neteverythingelse-800x446.jpg" alt="" class="wp-image-13228" style="aspect-ratio:1.793766994352646;width:389px;height:auto" srcset="https://jesseliberty.com/wp-content/uploads/2026/04/neteverythingelse-800x446.jpg 800w, https://jesseliberty.com/wp-content/uploads/2026/04/neteverythingelse-300x167.jpg 300w, https://jesseliberty.com/wp-content/uploads/2026/04/neteverythingelse-150x84.jpg 150w, https://jesseliberty.com/wp-content/uploads/2026/04/neteverythingelse-768x428.jpg 768w, https://jesseliberty.com/wp-content/uploads/2026/04/neteverythingelse.jpg 875w" sizes="(max-width: 800px) 100vw, 800px" /></figure>



<p>The advantage of the first is that you understand the underlying mechanisms in more depth; the advantage of the second is that a lot of the plumbing is done for you and you become more productive more quickly. </p>



<p>I will do the .NET work in C#, and probably do all the other work in Python. See my blogpost on why <a href="https://jesseliberty.com/2026/02/20/python/">Python</a>. </p>



<p>I will, to a degree, be documenting what I learn as I learn it, without infringing on copyright, of course.</p>



<span id="more-13227"></span>



<h2 class="wp-block-heading">Project 1 &#8211; Jupyter</h2>



<p>The work for Johns Hopkins is done in a Jupyter notebook. These are very convenient files that contain runnable cells. You put your code snippet in a cell and run it, either receiving a result or extensive error information. To get started, open Visual Studio Code and click New File. In the drop down on top, choose Jupyter Notebook:</p>



<figure class="wp-block-image size-full is-resized"><img decoding="async" width="598" height="147" src="https://jesseliberty.com/wp-content/uploads/2026/04/NewFile.jpg" alt="" class="wp-image-13229" style="width:431px;height:auto" srcset="https://jesseliberty.com/wp-content/uploads/2026/04/NewFile.jpg 598w, https://jesseliberty.com/wp-content/uploads/2026/04/NewFile-300x74.jpg 300w, https://jesseliberty.com/wp-content/uploads/2026/04/NewFile-150x37.jpg 150w" sizes="(max-width: 598px) 100vw, 598px" /></figure>



<p>Choose your Python environment, and put code into the first &#8220;cell.&#8221; Then click on the knob on the left and the cell runs and the output is displayed:</p>



<figure class="wp-block-image size-full is-resized"><img decoding="async" width="253" height="107" src="https://jesseliberty.com/wp-content/uploads/2026/04/image.png" alt="" class="wp-image-13230" style="width:220px;height:auto" srcset="https://jesseliberty.com/wp-content/uploads/2026/04/image.png 253w, https://jesseliberty.com/wp-content/uploads/2026/04/image-150x63.png 150w" sizes="(max-width: 253px) 100vw, 253px" /></figure>



<p>You can add markdown, you can even tell it to generate code based on your description of what you want. It is possible to have these cells generate a proper Python program and/or generate </p>



<pre class="wp-block-code"><code></code></pre>



<h2 class="wp-block-heading">Open AI Endpoint</h2>



<p>Whether you are working in the Jupyter notebook or in Agent Framework, you will want an OpenAI Endpoint. To do so go to https://platform.openai.com, sign in, go to API Keys, create a new key. Your endpoint is the base url used for API calls.</p>



<p>Or&#8230; if you are working in the Microsoft ecosystem, in the Azure Portal search for Azure OpenAI and create a resource. Then go to Resource Management -> Keys and Endpoint. Copy the Endpoint and Key 1 (your API key) Deploy under Resource Management -> Model Deployments. Your endpoint will look like this:</p>



<p><a href="https://.openai.azure.com/">https://&lt;your-resource-name>.openai.azure.com/</a><br /><br />Copilot can set all this up for you.</p>



<p>Next up: setting up your environment.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>AI: The Near Term</title>
		<link>https://jesseliberty.com/2026/03/30/ai-the-near-term/</link>
		
		<dc:creator><![CDATA[Jesse Liberty]]></dc:creator>
		<pubDate>Mon, 30 Mar 2026 11:49:06 +0000</pubDate>
				<category><![CDATA[Essentials]]></category>
		<guid isPermaLink="false">https://jesseliberty.com/?p=13222</guid>

					<description><![CDATA[As promised, I&#8217;ll be posting slides and commentary from my recent user-group presentation on AI (Boston Code Camp). One of my first slides talked about the near-term evolution of AI, defined as either 1-2 years or 6 months, depending on &#8230; <a href="https://jesseliberty.com/2026/03/30/ai-the-near-term/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
										<content:encoded><![CDATA[
<p>As promised, I&#8217;ll be posting slides and commentary from my recent user-group presentation on AI (<a href="https://www.bostoncodecamp.com/CC40/info">Boston Code Camp)</a>. One of my first slides talked about the near-term evolution of AI, defined as either 1-2 years or 6 months, depending on who you believe.</p>



<p>I divided the slide into two parts: good news and bad. The <strong>good news </strong>is the promise of enormously increased productivity, which may well lead to a higher standard of living across the board. Further, as AI progresses, we may see accelerated breakthroughs in many fields, most notably medicine and genetics.</p>



<figure class="wp-block-image size-large is-resized"><img loading="lazy" decoding="async" width="800" height="543" src="https://jesseliberty.com/wp-content/uploads/2026/03/image-2-800x543.png" alt="" class="wp-image-13223" style="aspect-ratio:1.4727297705728808;width:296px;height:auto" srcset="https://jesseliberty.com/wp-content/uploads/2026/03/image-2-800x543.png 800w, https://jesseliberty.com/wp-content/uploads/2026/03/image-2-300x204.png 300w, https://jesseliberty.com/wp-content/uploads/2026/03/image-2-150x102.png 150w, https://jesseliberty.com/wp-content/uploads/2026/03/image-2-768x521.png 768w, https://jesseliberty.com/wp-content/uploads/2026/03/image-2.png 810w" sizes="auto, (max-width: 800px) 100vw, 800px" /></figure>



<span id="more-13222"></span>



<p>The bad news is that along with these changes will almost certainly come massive displacement. As a society, we&#8217;ve seen this kind of displacement before. The advent of the tractor displaced well over 50% of farm workers, and ultimately mechanization displaced over 95% of agricultural labor! <br /><br />The key difference, however, is that in the past technology displaced the least skilled workers; AI is set to affect many of the most educated and skilled. I&#8217;m not sure that society knows how to handle this. Reskilling has a poor performance history, and sending highly paid college-educated programmers back to two-year training programs in robotics does not seem auspicious. </p>



<p>In the very short term, AI presents some real challenges, not least is the environmental impact of massive energy-consuming data centers. Add to that the potential economic impact when the AI boom goes bust and there is plenty to worry about, but here is one more&#8230;</p>



<p>Right now we are learning to adjust to AI, but research continues on AGI (Artificial General Intelligence). The next step after that is Artificial Super Intelligence: when AI becomes meaningfully smarter than humans. No one knows quite what to expect when that happens, but I commend to you the book <a href="https://bookshop.org/p/books/if-anyone-builds-it-everyone-dies-why-superhuman-ai-would-kill-us-all-eliezer-yudkowsky/2da88520a671d222?ean=9780316595643&amp;next=t"><em>If Anyone Builds It, Everyone Dies</em> </a>by <a href="https://www.amazon.com/Eliezer-Yudkowsky/e/B00J6XXP9K/ref=dp_byline_cont_ebooks_1">Eliezer Yudkowsk</a>y and <a href="https://www.amazon.com/Nate-Soares/e/B0FSF2C9PK/ref=dp_byline_cont_ebooks_2">Nate Soares</a>. These are not crackpot writers &#8212; they are recognized experts in AI and their thesis is chilling.</p>



<p>In coming postings I will divide my attention between two aspects of AI:</p>



<ul class="wp-block-list">
<li>Using AI in developing your application</li>



<li>Creating applications that incorporate AI</li>
</ul>



<p>Along the way I will talk about AI in the .NET world (specifically the Azure workflow tools) and outside of .NET (time to brush up on Python). </p>



<p>Next up: Assisted Coding&#8230;</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>MCP In Depth</title>
		<link>https://jesseliberty.com/2026/03/22/mcp-in-depth/</link>
		
		<dc:creator><![CDATA[Jesse Liberty]]></dc:creator>
		<pubDate>Sun, 22 Mar 2026 14:47:51 +0000</pubDate>
				<category><![CDATA[Essentials]]></category>
		<guid isPermaLink="false">https://jesseliberty.com/?p=13214</guid>

					<description><![CDATA[In a special videoCast, Lance McCarthy of Progress Software dives deep into MCP, not only explaining what it is for and how it works, but demonstrating, in code, how it is done. MCP (Model, Context, Protocol) is an open standard &#8230; <a href="https://jesseliberty.com/2026/03/22/mcp-in-depth/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
										<content:encoded><![CDATA[
<p>In a special <a href="https://youtube.com/jesseliberty">videoCast</a>, Lance McCarthy of Progress Software dives deep into MCP, not only explaining what it is for and how it works, but demonstrating, in code, how it is done. </p>



<p>MCP (Model, Context, Protocol) is an open standard that lets AI models (read copilot, ChatGPT, etc.) connect to external tools. These tools can be databases, code you write, code you connect to, other AIs, etc. etc. It is the universal API for Agents.</p>



<figure class="wp-block-image size-large is-resized"><img loading="lazy" decoding="async" width="800" height="303" src="https://jesseliberty.com/wp-content/uploads/2026/03/image-1-800x303.png" alt="" class="wp-image-13216" style="aspect-ratio:2.6403940886699506;width:473px;height:auto" srcset="https://jesseliberty.com/wp-content/uploads/2026/03/image-1-800x303.png 800w, https://jesseliberty.com/wp-content/uploads/2026/03/image-1-300x114.png 300w, https://jesseliberty.com/wp-content/uploads/2026/03/image-1-150x57.png 150w, https://jesseliberty.com/wp-content/uploads/2026/03/image-1-768x291.png 768w, https://jesseliberty.com/wp-content/uploads/2026/03/image-1.png 1045w" sizes="auto, (max-width: 800px) 100vw, 800px" /></figure>



<p><a href="https://github.com/LanceMcCarthy/McpServers">Here&#8217;s a link to the code</a>.</p>



<p></p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Get on the bus, or get run over by it</title>
		<link>https://jesseliberty.com/2026/03/17/get-on-the-bus-or-get-run-over-by-it/</link>
		
		<dc:creator><![CDATA[Jesse Liberty]]></dc:creator>
		<pubDate>Tue, 17 Mar 2026 20:49:53 +0000</pubDate>
				<category><![CDATA[AI]]></category>
		<guid isPermaLink="false">https://jesseliberty.com/?p=13208</guid>

					<description><![CDATA[On March 28 I&#8217;m presenting on Fundamentals of AI to the Boston Code Camp. While I will cover what you need to know about the various aspects of using and creating various AI components, the key message is it is &#8230; <a href="https://jesseliberty.com/2026/03/17/get-on-the-bus-or-get-run-over-by-it/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
										<content:encoded><![CDATA[
<p>On March 28 I&#8217;m presenting on <em>Fundamentals of AI</em> to the Boston Code Camp. While I will cover what you need to know about the various aspects of using and creating various AI components, the key message is <em><strong>it is time</strong></em>. It is time to start developing and honing your AI skills, or as I say in the title, you will be run over by the AI bus.</p>



<figure class="wp-block-image size-full is-resized"><img loading="lazy" decoding="async" width="800" height="535" src="https://jesseliberty.com/wp-content/uploads/2026/03/image.png" alt="" class="wp-image-13209" style="width:347px;height:auto" srcset="https://jesseliberty.com/wp-content/uploads/2026/03/image.png 800w, https://jesseliberty.com/wp-content/uploads/2026/03/image-300x201.png 300w, https://jesseliberty.com/wp-content/uploads/2026/03/image-150x100.png 150w, https://jesseliberty.com/wp-content/uploads/2026/03/image-768x514.png 768w" sizes="auto, (max-width: 800px) 100vw, 800px" /></figure>



<p>After the presentation, I&#8217;ll cover a lot of that material here, but to get us started let&#8217;s talk about the two ways you&#8217;ll care about AI. </p>



<ol class="wp-block-list">
<li>Using AI to aid you in your coding</li>



<li>Creating applications that incorporate AI</li>
</ol>



<span id="more-13208"></span>



<p>By now, you probably are using AI in your coding, although I&#8217;m willing to wager that most of us are not using it as well or as extensively as we might. I hope to expand on that as we go.</p>



<p>In a <a href="https://jesseliberty.com/2026/02/22/copilot-instructions-md/">previous post,</a> I talked about creating a copilot-instructions.md file (though you might want a CLAUDE.md file!). You&#8217;ll also want to create (at least) </p>



<ul class="wp-block-list">
<li>Memory.md // key facts and decisions you&#8217;ve made</li>



<li>Restart.md // what you were doing when you stopped</li>



<li>Mistakes.md // mistakes you don&#8217;t want copilot to make again</li>
</ul>



<p>Why? Because Claude and Copilot, etc., have limited short-term memories, and after a while they begin to forget what you&#8217;ve already done. You then periodically have copilot read these files (which you assiduously keep updated) and that provides context that helps copilot stay on track (for copilot, read Claude, etc.) I tend to do this every 15 minutes or so, and at the end of each session I&#8217;m sure to update all three files so that they are ready for the next session.</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p>For this, and every good idea I have about working well with AI, I&#8217;m deeply indebted to a number of smart people, first among them Jeff Blankenburg and his <a href="https://31daysofvibecoding.com/2026/01/01/what-is-vibe-coding/">31 Days of Vibe Coding</a> and Jamie Maguire&#8217;s <a href="https://jamiemaguire.net/index.php/2026/02/24/new-free-course-understanding-microsoft-agent-framework/">outstanding free course </a>on Microsoft&#8217;s Agent Framework. I can also highly recommend the Johns Hopkins 16-week course on Agentics, which I&#8217;m enjoying immensely. </p>
</blockquote>



<p>If Vibe Coding is what floats your boat, be sure to see <a href="https://www.youtube.com/watch?v=CYd4FXd7EsE&amp;t=404s">my interview with James Montemagno.</a> Start at about 3 minutes in if you&#8217;re in a rush.</p>



<p>So much to discuss. In coming posts I&#8217;ll cover three main topics:</p>



<ol class="wp-block-list">
<li>Using AI to enhance and simplify your coding (hey! copilot! what does this mean?)</li>



<li>Incorporating AI into your application</li>



<li>(really 2a) A working demo. At the moment it is HyperVideo, though I&#8217;m stuck on the fact that my video player keeps choking on the audio in my videos making everything freeze up. Any suggestions? Since I have to do some projects for my Agentics course, I may switch over to one or more of those. In any case, I&#8217;ll bring you along for the ride.</li>
</ol>



<p>The next topic, however, is MCP. Stay tuned; I&#8217;ll be recording a new, expanded videocast with Lance McCarthy on that very topic. <a href="https://www.youtube.com/watch?v=4u2SmHzz7Xc&amp;t=102s">Here&#8217;s the first one we did.</a> In the coming one we&#8217;ll dive deeper, with real live code and everything!</p>



<p>Much more soon&#8230;</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Boston Code Camp</title>
		<link>https://jesseliberty.com/2026/02/28/boston-code-camp/</link>
					<comments>https://jesseliberty.com/2026/02/28/boston-code-camp/#comments</comments>
		
		<dc:creator><![CDATA[Jesse Liberty]]></dc:creator>
		<pubDate>Sat, 28 Feb 2026 19:44:15 +0000</pubDate>
				<category><![CDATA[Essentials]]></category>
		<guid isPermaLink="false">https://jesseliberty.com/?p=13199</guid>

					<description></description>
										<content:encoded><![CDATA[
<figure class="wp-block-image size-full is-resized"><a href="https://bostoncodecamp.com"><img loading="lazy" decoding="async" width="748" height="757" src="https://jesseliberty.com/wp-content/uploads/2026/02/Boston-Code-Camp-1.jpg" alt="" class="wp-image-13201" style="aspect-ratio:0.988109229173868;width:370px;height:auto" srcset="https://jesseliberty.com/wp-content/uploads/2026/02/Boston-Code-Camp-1.jpg 748w, https://jesseliberty.com/wp-content/uploads/2026/02/Boston-Code-Camp-1-296x300.jpg 296w, https://jesseliberty.com/wp-content/uploads/2026/02/Boston-Code-Camp-1-148x150.jpg 148w" sizes="auto, (max-width: 748px) 100vw, 748px" /></a></figure>
]]></content:encoded>
					
					<wfw:commentRss>https://jesseliberty.com/2026/02/28/boston-code-camp/feed/</wfw:commentRss>
			<slash:comments>5</slash:comments>
		
		
			</item>
		<item>
		<title>HyperVideo – GitHub Issues</title>
		<link>https://jesseliberty.com/2026/02/23/hypervideo-github-issues/</link>
		
		<dc:creator><![CDATA[Jesse Liberty]]></dc:creator>
		<pubDate>Mon, 23 Feb 2026 18:07:12 +0000</pubDate>
				<category><![CDATA[Essentials]]></category>
		<guid isPermaLink="false">https://jesseliberty.com/?p=13187</guid>

					<description><![CDATA[In examining my HyperVideo project I decided that the Bunny video was a great placeholder, but what I really wanted was my own videos. What better place to start than the videos I have up on YouTube. How am I &#8230; <a href="https://jesseliberty.com/2026/02/23/hypervideo-github-issues/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
										<content:encoded><![CDATA[
<p>In examining my HyperVideo project I decided that the Bunny video was a great placeholder, but what I really wanted was <a href="https://youtube.com/jesseliberty">my own videos.</a> What better place to start than the videos I have up on YouTube. How am I going to do that?<br /><br />To get started, I asked CoPilot what it would take. CoPilot generated a plan of action. I took that and opened an issue on GitHub which will document what I have to do. </p>



<span id="more-13187"></span>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p>Replace the current HTML5 video player implementation with YouTube embedded player to integrate videos from the <a href="https://github.com/JesseLiberty">@JesseLiberty</a> YouTube channel while maintaining all existing interactive learning features.</p>



<p>Proposed Changes</p>



<ol class="wp-block-list">
<li>Replace HTML5 Video Player with YouTube Embed<br />• Implement YouTube IFrame embed in VideoLearning.razor<br />• Source videos from <a href="https://youtube.com/jesseliberty">https://youtube.com/jesseliberty</a> channel<br />• Replace</li>



<li>Maintain Existing Functionality<br />All current features must remain operational:<br />• <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Pause &amp; Inquire: Pause video and open question panel<br />• <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Interactive Transcript: Clickable, time-synchronized segments<br />• <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Time Tracking: Real-time display of current playback position<br />• <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Seeking: Click transcript to jump to timestamp<br />• <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Search Integration: Wikipedia, Wiktionary, YouTube, Stack Overflow, MDN</li>



<li>Use YouTube IFrame Player API<br />Implement programmatic video control using YouTube IFrame Player API:<br />• pauseVideo() &#8211; Pause playback<br />• playVideo() &#8211; Resume playback<br />• getCurrentTime() &#8211; Get current timestamp<br />• seekTo(seconds) &#8211; Jump to specific time<br />• getDuration() &#8211; Get video length<br />• Event listeners: onStateChange, onReady</li>



<li>Video Selection &amp; Configuration<br />• Video Dropdown: Add UI to select from multiple videos in <a href="https://github.com/JesseLiberty">@JesseLiberty</a> channel<br />• Video Catalog: Create a list/configuration of available educational videos with:<br />• YouTube video ID<br />• Title/description<br />• Associated transcript segments<br />• State Management: Store selected video ID in component state<br />• Configuration Options:<br />• Hardcode initial video list in component<br />• OR store in appsettings.json<br />• OR create a separate service/data file<br />Technical Considerations<br />JavaScript Interop Changes<br />• Load YouTube IFrame API script: <a href="https://www.youtube.com/iframe_api">https://www.youtube.com/iframe_api</a><br />• Create typed JavaScript interop wrapper for YouTube Player API<br />• Replace direct eval() calls with proper YouTube API method invocations<br />• Handle async initialization of YouTube player (onYouTubeIframeAPIReady)<br />Example JS Interop Pattern:</li>
</ol>



<p>// VideoLearning.razor.js<br />export function initializeYouTubePlayer(videoId, dotNetHelper) {<br />const player = new YT.Player(&#8216;player&#8217;, {<br />videoId: videoId,<br />events: {<br />&#8216;onReady&#8217;: onPlayerReady,<br />&#8216;onStateChange&#8217;: onPlayerStateChange<br />}<br />});<br />// Store player reference and expose methods<br />}</p>



<p>export function pauseVideo(player) {<br />player.pauseVideo();<br />}</p>



<p>export function getCurrentTime(player) {<br />return player.getCurrentTime();<br />}</p>



<p>Transcript Handling<br />• Option 1: Manually create transcript segments per video (current approach)<br />• Option 2: Fetch captions using YouTube Data API v3 (requires API key)<br />• Option 3: Store transcripts in separate JSON files mapped to video IDs<br />• Consider caption format: YouTube provides .srt or .vtt formats<br />Render Mode Compatibility<br />• Ensure YouTube IFrame API works with @rendermode InteractiveServer<br />• Test SignalR reconnection behavior with YouTube player state<br />• Verify StateHasChanged() triggers UI updates correctly<br />Files to Modify</p>



<ol class="wp-block-list">
<li>VideoLearning.razor<br />• Replace</li>



<li>Components/Pages/VideoLearning.razor.js (new file)<br />• Create typed JS module for YouTube Player API<br />• Export functions: initPlayer, pauseVideo, playVideo, seekTo, getCurrentTime<br />• Handle player events and callbacks to Blazor</li>



<li>Models/VideoInfo.cs (optional, new file)</li>
</ol>



<p>public record VideoInfo(string VideoId, string Title, List Transcript);</p>



<ol start="4" class="wp-block-list">
<li>appsettings.json (optional)<br />• Store video catalog configuration<br />Implementation Steps</li>



<li>Add YouTube IFrame API script reference to App.razor or VideoLearning.razor</li>



<li>Create VideoLearning.razor.js with YouTube Player API wrapper</li>



<li>Update VideoLearning.razor markup to use YouTube embed</li>



<li>Refactor C# interop calls to use YouTube-specific methods</li>



<li>Add video selection UI and catalog</li>



<li>Test all interactive features (pause/resume, seeking, transcript sync)</li>



<li>Update transcripts for selected YouTube videos from <a href="https://github.com/JesseLiberty">@JesseLiberty</a> channel<br />Success Criteria<br />• <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Videos from <a href="https://github.com/JesseLiberty">@JesseLiberty</a> YouTube channel play in the application<br />• <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Users can switch between multiple videos<br />• <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> All existing interactive features work identically<br />• <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Pause &amp; Inquire functionality remains intact<br />• <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Interactive transcript synchronization works<br />• <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Time tracking displays correctly<br />• <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Search integration functions as before<br />• <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> No degradation in user experience<br />Resources<br />• YouTube IFrame Player API Reference<br />• YouTube Data API v3 &#8211; Captions (for transcript retrieval)<br />• Blazor JavaScript Interop</li>
</ol>



<p>Labels: enhancement, feature, blazor, javascript-interop<br />Priority: High</p>
</blockquote>



<p>Those look like a great set of sub-tasks. I&#8217;m not sure how to attack them, but breaking them down will greatly simplify matters.</p>



<p>Here&#8217;s a first attempt at some of the sub-issues arising out of the work&#8230;</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="800" height="410" src="https://jesseliberty.com/wp-content/uploads/2026/02/image-800x410.png" alt="" class="wp-image-13188" srcset="https://jesseliberty.com/wp-content/uploads/2026/02/image-800x410.png 800w, https://jesseliberty.com/wp-content/uploads/2026/02/image-300x154.png 300w, https://jesseliberty.com/wp-content/uploads/2026/02/image-150x77.png 150w, https://jesseliberty.com/wp-content/uploads/2026/02/image-768x394.png 768w, https://jesseliberty.com/wp-content/uploads/2026/02/image.png 1150w" sizes="auto, (max-width: 800px) 100vw, 800px" /></figure>



<p>You can see that this is far from perfect. Some of these are small and some are huge. It will be necessary to flesh out some and to break others down to smaller tasks, but this is a good start. The trick is not to get overwhelmed. OK, I&#8217;m overwhelmed. But my buddy CoPilot and I are ready to tackle this.</p>



<p></p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>copilot-instructions.md</title>
		<link>https://jesseliberty.com/2026/02/22/copilot-instructions-md/</link>
					<comments>https://jesseliberty.com/2026/02/22/copilot-instructions-md/#comments</comments>
		
		<dc:creator><![CDATA[Jesse Liberty]]></dc:creator>
		<pubDate>Sun, 22 Feb 2026 20:18:02 +0000</pubDate>
				<category><![CDATA[Essentials]]></category>
		<guid isPermaLink="false">https://jesseliberty.com/?p=13184</guid>

					<description><![CDATA[When working with CoPilot in Visual Studio, the single most important thing is context. Context tells CoPilot what it is working on, what it should already know, what language conventions to use, etc., etc. CoPilot wants to help, but its &#8230; <a href="https://jesseliberty.com/2026/02/22/copilot-instructions-md/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
										<content:encoded><![CDATA[
<p>When working with CoPilot in Visual Studio, the single most important thing is <em>context</em>. Context tells CoPilot what it is working on, what it should already know, what language conventions to use, etc., etc. CoPilot wants to help, but its memory is not the best, and like the character in <a href="https://en.wikipedia.org/wiki/Memento_(film)">Memento</a>, the trick is to write everything down and remind it all the time&#8230; hence context.</p>



<p>The best way to get ahead of this is to create a copilot-instructions.md file in your .github directory (which you may need to create). In this file, you&#8217;ll want to put anything that CoPilot should know right from the get-go and for every session. </p>



<p>But how do you know what to put in there?</p>



<span id="more-13184"></span>



<p>Here&#8217;s the trick&#8230; let CoPilot build it for you! I cribbed a set of instructions from the &#8216;net that tells CoPilot how to create the file based on the existing code in my project. I tweaked it just a bit, as did a buddy (Teja) and all you need to do is copy it into the CoPilot window in Visual Studio, let CoPilot cook, and hey! presto! you have just what you want: a fully developed copilot-instructions.md file in just the right place. Even better, if you already have one, this will merge cleanly.</p>



<p>Here&#8217;s the instructions I give CoPilot:<br /><br /></p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p>Analyze this codebase to generate or update .github/<a href="http://copilot-instructions.md">copilot-instructions.md</a> for guiding AI coding agents. Focus on discovering the essential knowledge that would help an AI agent be immediately productive in this codebase. Consider aspects like: The &#8220;big picture&#8221; architecture that requires reading multiple files to understand &#8211; major components, service boundaries, data flows, and the &#8220;why&#8221; behind structural decisions Critical developer workflows (builds, tests, debugging) especially commands that aren&#8217;t obvious from file inspection alone Project-specific conventions and patterns that differ from common practices Integration points, external dependencies, and cross-component communication patterns  Guidelines (read more at <a href="https://aka.ms/vscode-instructions-docs">https://aka.ms/vscode-instructions-docs</a>): <br /><br />If .github/<a href="http://copilot-instructions.md">copilot-instructions.md</a> exists, merge intelligently &#8211; preserve valuable content while updating outdated sections Write concise, actionable instructions (~20-50 lines) using markdown structure Include specific examples from the codebase when describing patterns Avoid generic advice (&#8220;write tests&#8221;, &#8220;handle errors&#8221;) &#8211; focus on THIS project&#8217;s specific approaches Document only discoverable patterns, not aspirational practices Maintaining a history or features listing with a detailed description of all the information of the project into a <a href="http://README.md">README.md</a> file whenever there is a new change. Update the file accordingly with a brief summary. Before each task implementation, go through the <a href="http://README.md">README.md</a> file, then start implementing, understanding the whole picture of the requirements. Reference key files/directories that exemplify important patterns Update .github/<a href="http://copilot-instructions.md">copilot-instructions.md</a> for the user, then ask for feedback on any unclear or incomplete sections to iterate.</p>



<p>When writing unit tests use xunit and moq</p>
</blockquote>



<p>And here is the markdown file that CoPilot generated for me (put this into a file and open it in VS to see it displayed nicely):</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<pre class="wp-block-preformatted"><strong># GitHub Copilot Instructions for HyperVideo</strong>

HyperVideo is an interactive video learning platform built with <strong>**.NET 10**</strong> and <strong>**Blazor Server**</strong>. Users can pause videos, ask questions, and search multiple knowledge sources for learning resources.

<strong>## Project Structure</strong>

```
HyperVideo/
├── Components/
│   ├── App.razor               # Root component (HTML shell, Bootstrap, Blazor script)
│   ├── Routes.razor            # Router with 404 fallback and default layout
│   ├── _Imports.razor          # Global using directives for all components
│   ├── Layout/
│   │   ├── MainLayout.razor    # Two-column layout: sidebar NavMenu + main content area
│   │   ├── NavMenu.razor       # Navigation links (Home, Video Learning, Counter, Weather)
│   │   └── ReconnectModal.razor # SignalR reconnection overlay
│   └── Pages/
│       ├── Home.razor          # Landing page with link to video learning
│       ├── VideoLearning.razor # Core feature: interactive video player with inquiry panel
│       ├── Counter.razor       # Simple stateful counter demo
│       ├── Weather.razor       # Async data fetch demo with streaming render
│       ├── Error.razor         # Error boundary page
│       └── NotFound.razor      # 404 page
├── wwwroot/
│   ├── app.css                 # Global styles
│   └── lib/                   # Bootstrap 5 CSS/JS
├── Program.cs                  # App startup and middleware pipeline
├── appsettings.json
└── HyperVideo.csproj
```

<strong>## Technology Stack</strong>

- <strong>**Runtime**</strong>: .NET 10 (`net10.0`)
- <strong>**UI**</strong>: Blazor Server with Interactive Server rendering (`@rendermode InteractiveServer`)
- <strong>**Real-time**</strong>: ASP.NET Core SignalR (used implicitly by Blazor Server)
- <strong>**CSS**</strong>: Bootstrap 5, Bootstrap Icons (`bi-*`), component-scoped CSS files (`.razor.css`)
- <strong>**JS Interop**</strong>: `IJSRuntime` for controlling the HTML5 `&lt;video&gt;` element
- <strong>**Nullable**</strong>: enabled; <strong>**ImplicitUsings**</strong>: enabled

<strong>## Coding Conventions</strong>

<strong>### Blazor Components</strong>
- Place all pages under `Components/Pages/` with `@page "/route"` directives.
- Place shared layout under `Components/Layout/`.
- Use `@rendermode InteractiveServer` on pages that need interactivity (event handlers, JS interop).
- Component-scoped CSS goes in a sibling file named `ComponentName.razor.css`.
- Use `@code { }` blocks at the bottom of `.razor` files for C# logic.

<strong>### C# Style</strong>
- Follow standard C# conventions: PascalCase for types and methods, camelCase for private fields.
- Prefer `record` types for immutable data (e.g., `TranscriptSegment`).
- Use nullable reference types; annotate `string?` where null is expected.
- Use `string.Empty` instead of `""` for empty-string defaults.
- Prefer `async Task` over `async void` for event handlers.

<strong>### JavaScript Interop</strong>
- Inject `IJSRuntime` with `@inject IJSRuntime JS`.
- Prefer `JS.InvokeVoidAsync` for fire-and-forget calls and `JS.InvokeAsync&lt;T&gt;` when a return value is needed.
- Avoid `eval()` for new interop code; instead, expose named JavaScript functions in `wwwroot/` and call them by name.
- Always wrap JS interop calls in `try/catch` because the circuit may not be ready.

<strong>### State Management</strong>
- Use private fields and `StateHasChanged()` for local component state.
- Keep models close to where they are used; only extract to a separate file when shared across multiple components.

<strong>### Error Handling</strong>
- Wrap async event handlers in `try/catch` and log errors with `Console.WriteLine` or an injected `ILogger&lt;T&gt;`.
- Use the `Error.razor` page as the global error boundary (already wired via `&lt;ErrorBoundary&gt;`).

<strong>## Key Feature: VideoLearning.razor</strong>

`VideoLearning.razor` is the core component. Its responsibilities:

| Concern | Implementation |
|---|---|
| Video playback | HTML5 `&lt;video&gt;` element; JS interop to call `.pause()`, `.play()`, seek |
| Pause &amp; Inquire | Sets `isPaused = true`, shows inquiry panel with timestamp |
| Question search | Builds URL links to Wikipedia, Wiktionary, YouTube, Stack Overflow, MDN |
| Transcript | `List&lt;TranscriptSegment&gt;` displayed as clickable rows; active row highlighted |
| Time tracking | `@ontimeupdate` reads `currentTime` via JS interop |

When extending this component:
- Add new search sources by appending to `searchResults` inside `SearchForAnswer()`.
- Add transcript segments by adding `new TranscriptSegment(start, end, "text")` entries.
- Use `ElementReference` + `JS.InvokeVoidAsync("blazorHelpers.seekVideo", videoElement, time)` style helpers rather than bare `eval()`.

<strong>## Common Patterns</strong>

<strong>### Adding a New Page</strong>
```razor
@page "/my-page"
@rendermode InteractiveServer

&lt;PageTitle&gt;My Page&lt;/PageTitle&gt;

&lt;!-- markup --&gt;

@code {
    // component logic
}
```
Then add a `&lt;NavLink&gt;` entry in `NavMenu.razor`.

<strong>### Injecting a Service</strong>
Register in `Program.cs`:
```csharp
builder.Services.AddScoped&lt;IMyService, MyService&gt;();
```
Inject in component:
```razor
@inject IMyService MyService
```

<strong>### JS Interop Helper Pattern</strong>
Add a function to `wwwroot/app.js` (create if it does not exist):
```javascript
window.blazorHelpers = {
    seekVideo: (element, time) =&gt; { element.currentTime = time; }
};
```
Call from C#:
```csharp
await JS.InvokeVoidAsync("blazorHelpers.seekVideo", videoElement, time);
```

<strong>## Build &amp; Run</strong>

```bash
# Restore and run
 dotnet run --project HyperVideo/HyperVideo.csproj

# Build only
dotnet build HyperVideo/HyperVideo.csproj
```

Default URLs: `http://localhost:5092` / `https://localhost:7288`

<strong>## What to Avoid</strong>

- Do <strong>**not**</strong> use `@rendermode InteractiveWebAssembly` — this project is Blazor Server only.
- Do <strong>**not**</strong> add NuGet packages without checking compatibility with `net10.0`.
- Do <strong>**not**</strong> use bare `eval()` strings for new JS interop; prefer named helper functions.
- Do <strong>**not**</strong> use `async void` event handlers; use `async Task` and handle exceptions.
- Do <strong>**not**</strong> store secrets in `appsettings.json`; use environment variables or the .NET Secret Manager.
</pre>
</blockquote>



<p>This is based on the skeleton program written in the past couple of postings, so it didn&#8217;t have all that much to go on. Nonetheless, it created a great context file with very specific instructions for CoPilot that will create a consistent interface and programming approach.</p>



<p>More to come as we develop HyperVideo but this will put us on the right track straight away.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://jesseliberty.com/2026/02/22/copilot-instructions-md/feed/</wfw:commentRss>
			<slash:comments>6</slash:comments>
		
		
			</item>
		<item>
		<title>Python??</title>
		<link>https://jesseliberty.com/2026/02/20/python/</link>
					<comments>https://jesseliberty.com/2026/02/20/python/#comments</comments>
		
		<dc:creator><![CDATA[Jesse Liberty]]></dc:creator>
		<pubDate>Fri, 20 Feb 2026 11:51:54 +0000</pubDate>
				<category><![CDATA[Essentials]]></category>
		<guid isPermaLink="false">https://jesseliberty.com/?p=13180</guid>

					<description><![CDATA[This series on AI is going to take two paths: If you are writing apps, you have a couple choices (well, more than a couple). One choice is to stay in the Azure/.NET world, in which case C# is just &#8230; <a href="https://jesseliberty.com/2026/02/20/python/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
										<content:encoded><![CDATA[
<p>This series on AI is going to take two paths:</p>



<ul class="wp-block-list">
<li>Writing prompts</li>



<li>Writing apps that integrate AI (see <a href="https://jesseliberty.com/2026/01/20/an-ai-project/">Hypervideo</a>)</li>
</ul>



<p>If you are writing apps, you have a couple choices (well, more than a couple). One choice is to stay in the Azure/.NET world, in which case C# is just fine. The other (set of) choice(s) is to work in the rest of AI development, in which case Python is the language of choice.</p>



<p>I&#8217;m taking a course on agentics from Johns Hopkins University, and that course is in Python. It turns out that learning Python is pretty easy if you are a C# programmer, and it is even easier if you are a C# programmer with access to CoPilot and/or ChatGPT for Python. </p>



<p>I resisted learning Python all these years, but I&#8217;ve come to believe that if you are serious about AI then Python is in your future. So, might as well bite the bullet and get started now.</p>



<span id="more-13180"></span>



<h2 class="wp-block-heading">It&#8217;s Just Syntax</h2>



<p>All the concepts are the same (more or less). There are variables, loops, dictionaries, tuples and so forth. Some of the syntax is different (no braces) and some of the rules vary a bit (tuples are immutable), but it won&#8217;t take you long to learn. Let&#8217;s start with the basics.</p>



<p><strong>DataTypes</strong>: Python has only three numeric datatypes: int, float and complex. It also has str (string) and bool. One thing to watch for is truthy v true. True requires a bool but truthy is anything that evaluates to true. Huh? If a variable is of type bool, it can only. have one of two values: true or false. But an expression can evaluate to true (e.g., 5+7 = 12) which is truthy.</p>



<p>There are also collections. some are ordered: list (which is mutable), tuple (which is not mutable) and range (which is an immutable arithmetic progression). In addition, there is dict &#8212; a dictionary which works much like a dictionary in c#</p>



<p>If you need a dictionary with unique values, there is the set, which comes in two flavors: set (mutable) and frozenset (immutable)</p>



<p>Finally, None does the work of void</p>



<p>According to ChatGPT the core types you&#8217;ll use 90% of the time are:</p>



<ul class="wp-block-list">
<li>int</li>



<li>float</li>



<li>str</li>



<li>bool</li>



<li>list</li>



<li>dict</li>



<li>tuple</li>



<li>set</li>



<li>none</li>
</ul>



<p>which pretty much corresponds to the big types in c# (except, perhaps set).</p>



<p><strong>Indentation</strong> One big thing for C# programmers to watch out for is indentation. Python does not use braces in if statements, functions, etc.; it uses indentation.</p>



<pre class="wp-block-code"><code>if (myAge > 5)
   print("You are a big boy")
else
   print("You still have some growing to do")
   print("But don't worry, we all went through it")
print("this line is not in the if/else")</code></pre>



<p>Notice that the last print statement is not in the if/else construct. Oh, there is also an elif statement so that you can have if, elif, elif, else.</p>



<p><strong>Function definition</strong> You define a function with the keyword <strong>def</strong> and you use indentation to set the contents of the function:</p>



<pre class="wp-block-code"><code>def greet(name):
    print("Hello")
    print(name)
</code></pre>



<p> Some quick rules on indentation:</p>



<ul class="wp-block-list">
<li>Typically you indent 4 spaces (but that is not really a rule)</li>



<li>All indentation must be the same amount</li>



<li>You cannot mix tabs and spaces</li>
</ul>



<p>Don&#8217;t forget to nest your indentation</p>



<pre class="wp-block-code"><code>def check_age(age):
    if age >= 21:
        print("Can drink")
    else:
        print("Cannot drink")
</code></pre>



<p><strong>Lists</strong> Lists are created with square brackets</p>



<pre class="wp-block-code"><code>numbers = &#91;10, 20, 30, 40]</code></pre>



<p>Notice you do not put the type. You never declare the type, it is inferred. (this is true for all declarations, not just collections)</p>



<p>You iterate over lists with a very similar syntax to C#&#8217;s foreach</p>



<pre class="wp-block-code"><code>for number in numbers:
   print(number)</code></pre>



<p>Don&#8217;t forget the colon!</p>



<p><strong>Dictionaries</strong> Dictionaries are similar to lists, but you declare them with curly braces. You iterate over them using the key and the value:</p>



<pre class="wp-block-code"><code>students = {
    1001: "Alice",
    1002: "Bob"
}

for student_id, name in students.items():
    print(student_id, name)
</code></pre>



<p>This will print</p>



<pre class="wp-block-code"><code>1001 Alice
1002 Bob</code></pre>



<p>You can access both with .items() or the keys with .keys() or the values with .values()</p>



<p><strong>Tuples</strong> Tuples can be declared with or without parentheses</p>



<pre class="wp-block-code"><code>coordinates = (15, 20)
colors = ("red", "greeen", "blue", "yellow")
point = 5,10</code></pre>



<p>You can iterate over a tuple</p>



<pre class="wp-block-code"><code>for color in colors:
   print(color)</code></pre>



<p>A common thing to do with tuples is called unpacking. For example, using the point from above, you can write</p>



<pre class="wp-block-code"><code>point = (10, 20)

x, y = point
print(x)  # 10
print(y)  # 20</code></pre>



<p>Or you can use this in loops, which is a common construct</p>



<pre class="wp-block-code"><code>pairs = ((1, "A"), (2, "B"), (3, "C"))

for number, letter in pairs:
    print(number, letter)</code></pre>



<p>That&#8217;s plenty to get you started with Python. Of course there are more advanced constructs, and we&#8217;ll tackle them as we go, but these are the fundamentals.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://jesseliberty.com/2026/02/20/python/feed/</wfw:commentRss>
			<slash:comments>7</slash:comments>
		
		
			</item>
		<item>
		<title>HyperVideo Features</title>
		<link>https://jesseliberty.com/2026/01/24/hypervideo-features/</link>
					<comments>https://jesseliberty.com/2026/01/24/hypervideo-features/#comments</comments>
		
		<dc:creator><![CDATA[Jesse Liberty]]></dc:creator>
		<pubDate>Sat, 24 Jan 2026 18:32:56 +0000</pubDate>
				<category><![CDATA[AI]]></category>
		<guid isPermaLink="false">https://jesseliberty.com/?p=13175</guid>

					<description><![CDATA[In a previous post, I laid out the basic idea of an AI demonstration project I call HyperVideo. In this short post, I&#8217;d like to review some of the features I imagine for this project. Some will be implemented in &#8230; <a href="https://jesseliberty.com/2026/01/24/hypervideo-features/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
										<content:encoded><![CDATA[
<p>In <a href="https://jesseliberty.com/2026/01/20/an-ai-project/">a previous post,</a> I laid out the basic idea of an AI demonstration project I call HyperVideo. In this short post, I&#8217;d like to review some of the features I imagine for this project. Some will be implemented in the MVP, some after the initial &#8220;release,&#8221; and some are simply aspirational.</p>



<span id="more-13175"></span>



<ol class="wp-block-list">
<li>Run the video and show a transcript in real time</li>



<li>Pause the video and type in any question on related or other topics (first cut)</li>



<li>Add speech recognition</li>



<li>Pause the video and be offered questions related to what was just said in the video</li>



<li>Ask a question and see a (hyper) video in response (a button appears to take you back one video)</li>



<li>Add text-to-speech to answer questions</li>



<li>Add history of previous questions to serve as context for future questions</li>



<li>Add quizzes at the end of the video</li>



<li>Add ability to scroll back in the transcript and be offered questions about the selected time slice or hypervideo link from there</li>



<li>Add hyperlinks to the transcript. Following the link potentially brings up new videos</li>
</ol>



<p>More to follow, I&#8217;m sure, but that&#8217;s a pretty good starting list.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://jesseliberty.com/2026/01/24/hypervideo-features/feed/</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
			</item>
		<item>
		<title>Essential Programmer Utilities</title>
		<link>https://jesseliberty.com/2026/01/22/essential-programmer-utilities/</link>
					<comments>https://jesseliberty.com/2026/01/22/essential-programmer-utilities/#comments</comments>
		
		<dc:creator><![CDATA[Jesse Liberty]]></dc:creator>
		<pubDate>Thu, 22 Jan 2026 11:10:47 +0000</pubDate>
				<category><![CDATA[Essentials]]></category>
		<guid isPermaLink="false">https://jesseliberty.com/?p=13170</guid>

					<description><![CDATA[Every two years or so I publish a list of the utilities I find indispensable. It is interesting to me which ones last year after year (e.g., Evernote) and which fall off the list—often because the functionality I want has &#8230; <a href="https://jesseliberty.com/2026/01/22/essential-programmer-utilities/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
										<content:encoded><![CDATA[
<p>Every two years or so I publish a list of the utilities I find indispensable. It is interesting to me which ones last year after year (e.g., Evernote) and which fall off the list—often because the functionality I want has been absorbed into Microsoft software I&#8217;m already using.</p>



<p>Here is 2026&#8217;s list&#8230;</p>



<span id="more-13170"></span>



<p><em>Lists are always subjective, but it is helpful, I think, to exchange favorites now and again. Here’s my list <strong>in no particular order</strong></em></p>



<ol class="wp-block-list">
<li><a href="https://visualstudio.microsoft.com/">Visual Studio 202</a>6 – goes without saying that this is the world’s best IDE for .NET developers. I use it 8-12 hours a day; it just keeps getting better, especially with CoPilot.</li>



<li><a href="https://github.com/features/copilot">Copilot</a> – AI done right. Integrated with Visual Studio, this add-on is the most powerful and useful tool I have. It can get in the way a little, but when it does its stuff, watch out. Point it at a class and ask for documentation and/or unit tests and watch it go! More powerful is CoPilot Agents which will cook up substantial amounts of excellent code. But kids, don’t try this at home—it needs adult supervision.</li>



<li><a href="https://www.prestosoft.com/edp_examdiffpro.asp?flm=1">ExamDiffPro</a> – there are lots of comparison/merge utilities. Get a good one.</li>



<li><a href="https://marketplace.visualstudio.com/items?itemName=MadsKristensen.Tweaks">Tweaks </a>by Mads Kristensen — small but very valuable addition to VS</li>



<li><a href="https://evernote.com/">Evernote</a>: I use it to log everything I do, including every fix for recurring issues. It is quick, powerful, and easy to use. Although it has limitations, overall, I’ve found it helpful and reliable and it now holds thousands of notes for me. It does have a new transcription ability, but I find it somewhat limited (no summary, etc.) for that I use&#8230;</li>



<li>TalkNotes. This incredibly flexible iOS utility does just what it says: it takes notes and then will produce those notes in any number of ways, including custom reports. I use only a small portion of its potential, but they are critical to my workflow. (1) I use it to summarize meetings and tell me the action items, and (2) I dictate to it as I work so that I can ask, &#8220;What did I do 5 minutes ago that made this all break?&#8221; Note: this application type is exploding and there are many great competitors. One I have my eye on is Wave, which offers the ability to make inquiries about your meeting and which uses generative AI to provide meaningful answers.</li>



<li><a href="https://wisprflow.ai/">WhisprFlow</a> &#8211; by far the best dictation software I&#8217;ve seen. Only caveat is that this is for relatively brief dictation &#8211; enough to send a message, not enough to replace TalkNotes or Wave. On the other hand, WhisprFlow is available on iOS, Android, Mac, and Windows and works well on all (I don&#8217;t have Android, so can&#8217;t swear to that). </li>



<li><a href="https://www.roboform.com/">Roboform</a> my password manager. I’d be lost without it. There are many, but this one is extremely straightforward and has been reliable for a very long time.</li>



<li><a href="https://bsky.app/profile/jesseliberty.com">BlueSky</a>—the single best social media site for .NET programmers</li>



<li>A note about Resharper. Many C# developers find it indispensable. Probably because I never became really proficient with it, and because VS has so many refactorings built in, I do not have it on my computer. But you may want to.</li>
</ol>



<p>Note that nearly all of these are free. I do remember the days when a program like Lotus 123 cost something in the hundreds of dollars. It makes me laugh when I see people look at an app and say, “$4, naah, too expensive.” On the other hand, watch out for the AI apps, they can be over $100 / year.</p>



<p><em>I am not affiliated with any of these.</em></p>



<p></p>
]]></content:encoded>
					
					<wfw:commentRss>https://jesseliberty.com/2026/01/22/essential-programmer-utilities/feed/</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
			</item>
	</channel>
</rss>