<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:media="http://search.yahoo.com/mrss/"><channel><title><![CDATA[Kurtis Welch]]></title><description><![CDATA[Start-ups, UX, Technology]]></description><link>https://www.kurtiswelch.com/</link><image><url>https://www.kurtiswelch.com/favicon.png</url><title>Kurtis Welch</title><link>https://www.kurtiswelch.com/</link></image><generator>Ghost 2.19</generator><lastBuildDate>Sun, 18 Jan 2026 10:20:03 GMT</lastBuildDate><atom:link href="https://www.kurtiswelch.com/rss/" rel="self" type="application/rss+xml"/><ttl>60</ttl><item><title><![CDATA[LinqPad Source Control]]></title><description><![CDATA[<p>I often have a bunch of linqpad scripts for a specific project that I want to include in that project's source control. I also don't want to have to change my LinqPad source directory every time I swap to working on a different project.</p><p>The solution: Create a "Directory Junction"</p>]]></description><link>https://www.kurtiswelch.com/linqpad/</link><guid isPermaLink="false">60abbb60b3194504dfcf06c9</guid><dc:creator><![CDATA[Kurtis Welch]]></dc:creator><pubDate>Mon, 24 May 2021 14:47:32 GMT</pubDate><content:encoded><![CDATA[<p>I often have a bunch of linqpad scripts for a specific project that I want to include in that project's source control. I also don't want to have to change my LinqPad source directory every time I swap to working on a different project.</p><p>The solution: Create a "Directory Junction" in the LinqPad directory that points at a folder in your project's directory.</p><p>Just run the following in a command prompt with elevated privileges.</p><!--kg-card-begin: html--><pre><code>mklink /J G:\Code\LinqPad\MyProjectName G:\Code\Projects\MyProjectName\LinqPad</code></pre><!--kg-card-end: html--><p>This basically makes it so that G:\Code\LinqPad\MyProjectName and G:\Code\Projects\MyProjectName\LinqPad are the same folder. Anything you do to one folder happens to the other folder. Magic.</p>]]></content:encoded></item><item><title><![CDATA[Game Server DDoS Protection Swarm]]></title><description><![CDATA[<p>The first company I founded was running a network of dozens of Minecraft servers that supported around 15k concurrent players. Our servers were being constantly attacked with DDoS attacks, causing widespread disruption of services. I designed a solution where we had a "swarm" of hundreds of IP addresses across dozens</p>]]></description><link>https://www.kurtiswelch.com/game-server-ddos-protection-swarm/</link><guid isPermaLink="false">5f4e960eb3194504dfcf068e</guid><category><![CDATA[Work]]></category><dc:creator><![CDATA[Kurtis Welch]]></dc:creator><pubDate>Tue, 01 Sep 2020 18:43:33 GMT</pubDate><content:encoded><![CDATA[<p>The first company I founded was running a network of dozens of Minecraft servers that supported around 15k concurrent players. Our servers were being constantly attacked with DDoS attacks, causing widespread disruption of services. I designed a solution where we had a "swarm" of hundreds of IP addresses across dozens of proxy servers spread across different data centers across the country. We set up our DNS service (Route53 on AWS) to resolve game domains as a random IP for a proxy server from a datacenter that's geographically close to the player. We configured the proxy servers to "blackhole" any IP address that a DDoS attack was detected on.</p><p>This configuration protected us in two ways. If a DDoS attack was targeted at one IP address, players connected to that IP (&lt;1% of players) would be booted, and players connected to that proxy server (3-4% of players) would suffer a minute or two of decreased network performance (lag). So, still some disruption was possible, but it was minimized to acceptable levels. Additionally, if a DDoS attack was targeted at a domain name, each attacking client would be assigned a different random IP address, spreading the attack across many servers in several different data centers, nullifying the attack entirely.</p>]]></content:encoded></item><item><title><![CDATA[Work Sample - KPI Dashboard]]></title><description><![CDATA[<p>KPI Dashboard I built for ZenSales. It breaks all KPIs down weekly and quarterly. On the Upgrades To and Downgrades To columns, you can mouse over the stat for any week/quarter total and see where those upgrades / downgrades come from.</p><!--kg-card-begin: image--><figure class="kg-card kg-image-card kg-width-wide"><img src="https://www.kurtiswelch.com/content/images/2020/09/9A4u-1-.png" class="kg-image"></figure><!--kg-card-end: image--><!--kg-card-begin: html--><a href="http://coppy.me/9d/9A4u.png" target="_blank">Full Screen View</a><!--kg-card-end: html-->]]></description><link>https://www.kurtiswelch.com/work-sample-kpi-dashboard/</link><guid isPermaLink="false">5f4e6a24b3194504dfcf0670</guid><category><![CDATA[Work]]></category><dc:creator><![CDATA[Kurtis Welch]]></dc:creator><pubDate>Tue, 01 Sep 2020 15:37:58 GMT</pubDate><content:encoded><![CDATA[<p>KPI Dashboard I built for ZenSales. It breaks all KPIs down weekly and quarterly. On the Upgrades To and Downgrades To columns, you can mouse over the stat for any week/quarter total and see where those upgrades / downgrades come from.</p><!--kg-card-begin: image--><figure class="kg-card kg-image-card kg-width-wide"><img src="https://www.kurtiswelch.com/content/images/2020/09/9A4u-1-.png" class="kg-image"></figure><!--kg-card-end: image--><!--kg-card-begin: html--><a href="http://coppy.me/9d/9A4u.png" target="_blank">Full Screen View</a><!--kg-card-end: html-->]]></content:encoded></item><item><title><![CDATA[Visual Studio 2019 web page doesn't update when updating cshtml]]></title><description><![CDATA[<p>After ASP.net Core 3.0, runtime compilation is enabled using the Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation package. To enable runtime compilation, apps must:</p><p><strong><strong>Install the <code>Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation</code> NuGet package.</strong></strong></p><p><strong><strong>Update the project's Startup</strong></strong>.ConfigureServices method to include a call to AddRazorRuntimeCompilation:</p><!--kg-card-begin: code--><pre><code>services
    .AddControllersWithViews()
    .AddRazorRuntimeCompilation();</code></pre><!--kg-card-end: code-->]]></description><link>https://www.kurtiswelch.com/visual-studio-2019-web-page-doesnt-update-when-updating-cshtml/</link><guid isPermaLink="false">5e34582282f48b11898f6bfc</guid><dc:creator><![CDATA[Kurtis Welch]]></dc:creator><pubDate>Fri, 31 Jan 2020 16:40:21 GMT</pubDate><content:encoded><![CDATA[<p>After ASP.net Core 3.0, runtime compilation is enabled using the Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation package. To enable runtime compilation, apps must:</p><p><strong><strong>Install the <code>Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation</code> NuGet package.</strong></strong></p><p><strong><strong>Update the project's Startup</strong></strong>.ConfigureServices method to include a call to AddRazorRuntimeCompilation:</p><!--kg-card-begin: code--><pre><code>services
    .AddControllersWithViews()
    .AddRazorRuntimeCompilation();</code></pre><!--kg-card-end: code-->]]></content:encoded></item><item><title><![CDATA[FAQ Page JSON-LD Generator]]></title><description><![CDATA[<p>Click the link below to generate FAQ Page JSON-LD to embed on your website.</p><h2 id="faq-page-generator"><a href="http://coppy.me/W1ks/faq-editor.html">FAQ Page Generator</a></h2><p></p><p>Thanks!</p>]]></description><link>https://www.kurtiswelch.com/json-ld-faq-page/</link><guid isPermaLink="false">5e29d0eb82f48b11898f6be5</guid><dc:creator><![CDATA[Kurtis Welch]]></dc:creator><pubDate>Thu, 23 Jan 2020 17:01:07 GMT</pubDate><media:content url="https://www.kurtiswelch.com/content/images/2020/01/black-and-white-business-career-close-up-221164.jpg" medium="image"/><content:encoded><![CDATA[<img src="https://www.kurtiswelch.com/content/images/2020/01/black-and-white-business-career-close-up-221164.jpg" alt="FAQ Page JSON-LD Generator"><p>Click the link below to generate FAQ Page JSON-LD to embed on your website.</p><h2 id="faq-page-generator"><a href="http://coppy.me/W1ks/faq-editor.html">FAQ Page Generator</a></h2><p></p><p>Thanks!</p>]]></content:encoded></item><item><title><![CDATA[Simple Raffle Form]]></title><description><![CDATA[<p>Use this simple raffle tool to collect names and email addresses at events. The results are stored locally on your device and nothing is transmitted over the internet - giving you maximum privacy, while allowing you to collect entries with <em>no internet connection required!</em></p><p>Use the following to access the</p>]]></description><link>https://www.kurtiswelch.com/simple-raffle-form/</link><guid isPermaLink="false">5cfe603082f48b11898f6b9d</guid><category><![CDATA[Tools]]></category><dc:creator><![CDATA[Kurtis Welch]]></dc:creator><pubDate>Mon, 10 Jun 2019 13:59:15 GMT</pubDate><media:content url="https://www.kurtiswelch.com/content/images/2019/06/dylan-nolte-559758-unsplash.jpg" medium="image"/><content:encoded><![CDATA[<img src="https://www.kurtiswelch.com/content/images/2019/06/dylan-nolte-559758-unsplash.jpg" alt="Simple Raffle Form"><p>Use this simple raffle tool to collect names and email addresses at events. The results are stored locally on your device and nothing is transmitted over the internet - giving you maximum privacy, while allowing you to collect entries with <em>no internet connection required!</em></p><p>Use the following to access the admin interface:<br>Name: admin<br>Email: admin</p><p>Inside the admin interface, you can pick one or multiple winners, delete accidental entries, and see all entries. You can export the entries by simply copying and pasting them into a spreadsheet - just choose "Paste Values Only" when pasting into the spreadsheet.</p><h3 id="start-your-raffle"><a href="https://s3.amazonaws.com/static.kurtiswelch.com/Raffle.html">Start your raffle</a></h3>]]></content:encoded></item><item><title><![CDATA[Household revenue share]]></title><description><![CDATA[<p>My ex and I want to both contribute an equal percentage of our income to our household, but cap the total monthly contribution for both of us combined. For example, if I make $10k and she makes $7k, and we want to contribute 35% of our income to our "household</p>]]></description><link>https://www.kurtiswelch.com/household-revenue-share/</link><guid isPermaLink="false">5cc9fcd882f48b11898f6b2e</guid><category><![CDATA[Relationships]]></category><dc:creator><![CDATA[Kurtis Welch]]></dc:creator><pubDate>Wed, 01 May 2019 20:54:16 GMT</pubDate><media:content url="https://www.kurtiswelch.com/content/images/2019/05/accounting-adult-banknotes-210990.jpg" medium="image"/><content:encoded><![CDATA[<img src="https://www.kurtiswelch.com/content/images/2019/05/accounting-adult-banknotes-210990.jpg" alt="Household revenue share"><p>My ex and I want to both contribute an equal percentage of our income to our household, but cap the total monthly contribution for both of us combined. For example, if I make $10k and she makes $7k, and we want to contribute 35% of our income to our "household fund", BUT contribute only up to $5k combined, how much would we each contribute? Here is a quick calculator to help.</p><!--kg-card-begin: html--><iframe style="width: 400px; height: 1600px" src="https://s3.amazonaws.com/static.kurtiswelch.com/HouseholdContributions.html" border="0">
<!--kg-card-end: html--></iframe>]]></content:encoded></item><item><title><![CDATA[Setting up an Ubuntu Server]]></title><description><![CDATA[<p>Here's a quick script I run when first setting up an Ubuntu server. Makes it a little easier to use, a little more secure. </p><!--kg-card-begin: markdown--><ul>
<li>Use Google's DNS</li>
<li>Automatically sync time</li>
<li>Install Zip, screen, vnstat, sysstat, s3tools</li>
<li>Auto-ban IPs if they try to log in too many times</li>
</ul>
<!--kg-card-end: markdown--><!--kg-card-begin: markdown--><p><code>echo &quot;nameserver</code></p>]]></description><link>https://www.kurtiswelch.com/setting-up-an-ubuntu-server/</link><guid isPermaLink="false">5cb4bdf582f48b11898f6acb</guid><dc:creator><![CDATA[Kurtis Welch]]></dc:creator><pubDate>Mon, 15 Apr 2019 17:31:01 GMT</pubDate><content:encoded><![CDATA[<p>Here's a quick script I run when first setting up an Ubuntu server. Makes it a little easier to use, a little more secure. </p><!--kg-card-begin: markdown--><ul>
<li>Use Google's DNS</li>
<li>Automatically sync time</li>
<li>Install Zip, screen, vnstat, sysstat, s3tools</li>
<li>Auto-ban IPs if they try to log in too many times</li>
</ul>
<!--kg-card-end: markdown--><!--kg-card-begin: markdown--><p><code>echo &quot;nameserver 8.8.8.8&quot; &gt; /etc/resolv.conf; echo &quot;nameserver 8.8.4.4&quot; &gt;&gt; /etc/resolv.conf; apt-get -y install zip; apt-get -y install screen; apt-get -y install vnstat; apt-get -y install sysstat; wget -O- -q http://s3tools.org/repo/deb-all/stable/s3tools.key | sudo apt-key add - &amp;&amp; sudo wget -O/etc/apt/sources.list.d/s3tools.list http://s3tools.org/repo/deb-all/stable/s3tools.list &amp;&amp; sudo apt-get update &amp;&amp; sudo apt-get install s3cmd; sed -i -e 's@Port 22@Port 46279@' /etc/ssh/sshd_config; sed -i -e 's@Port 1157@Port 46279@' /etc/ssh/sshd_config; service ssh reload; cd; /etc/init.d/dns-clean start; ntpdate ntp.ubuntu.com; apt-get -y install ntp; apt-get -y install fail2ban; reboot now;</code></p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Windows Junk Folder - Open a new "junk" folder on windows with a single click]]></title><description><![CDATA[... a shortcut to a batch script that creates a new folder on my "junk" drive (j:) and opens the folder. One click, new folder to dump crap into. EZPZ. ]]></description><link>https://www.kurtiswelch.com/windows-junk-folder/</link><guid isPermaLink="false">5ca4ee6e82f48b11898f6a0b</guid><category><![CDATA[Code]]></category><dc:creator><![CDATA[Kurtis Welch]]></dc:creator><pubDate>Wed, 03 Apr 2019 17:51:16 GMT</pubDate><media:content url="https://www.kurtiswelch.com/content/images/2019/04/george-pagan-iii-1391887-unsplash.jpg" medium="image"/><content:encoded><![CDATA[<img src="https://www.kurtiswelch.com/content/images/2019/04/george-pagan-iii-1391887-unsplash.jpg" alt="Windows Junk Folder - Open a new "junk" folder on windows with a single click"><p>I can't count how many times I've just needed a random junk folder to dump some temporary data or, or to use to dump some quick logs or working files. A lot of times, it ends up cluttering my desktop. Or I messily reuse a folder for the thousandth time.</p><p>My eventual solution to this problem was to create a toolbar on my windows 10 desktop. In this toolbar I include a handful of quick links to folders I often want to go to... AND a shortcut to a batch script that creates a new folder on my "junk" drive (j:) and opens the folder. One click, new folder to dump crap into. EZPZ. Just make sure to change j: and my paths to whatever make sense to you.</p><!--kg-card-begin: html--><code><pre>@echo off
for /f "tokens=2 delims==" %%a in ('wmic OS Get localdatetime /value') do set "dt=%%a"
set "YY=%dt:~2,2%" & set "YYYY=%dt:~0,4%" & set "MM=%dt:~4,2%" & set "DD=%dt:~6,2%"
set "HH=%dt:~8,2%" & set "Min=%dt:~10,2%" & set "Sec=%dt:~12,2%"

set "datestamp=%YYYY%%MM%%DD%" & set "timestamp=%HH%%Min%%Sec%"
set "fullstamp=%YYYY%-%MM%-%DD%_%HH%-%Min%-%Sec%"


cd j:
mkdir j:\temp
mkdir j:\temp\%fullstamp%
explorer j:\temp\%fullstamp%</pre></code>
<!--kg-card-end: html-->]]></content:encoded></item></channel></rss>