<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Katie</title>
    <description>The latest articles on DEV Community by Katie (@katiekodes).</description>
    <link>https://dev.to/katiekodes</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F111743%2Fac59c51d-53ca-48b4-af45-59f8550e7474.png</url>
      <title>DEV Community: Katie</title>
      <link>https://dev.to/katiekodes</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/katiekodes"/>
    <language>en</language>
    <item>
      <title>Low-Code Generation Z</title>
      <dc:creator>Katie</dc:creator>
      <pubDate>Thu, 02 May 2024 09:00:00 +0000</pubDate>
      <link>https://dev.to/katiekodes/low-code-generation-z-11dg</link>
      <guid>https://dev.to/katiekodes/low-code-generation-z-11dg</guid>
      <description>&lt;p&gt;I've seen a lot of handwringing about &lt;a href="https://www.theverge.com/22684730/students-file-folder-directory-structure-education-gen-z"&gt;Generation Z not grokking hierarchichal file folders and directories&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;At the other end of the spectrum, &lt;a href="https://www-users.york.ac.uk/~dk135/research/low-code/"&gt;software engineering professor Dimitris Kolovos wrote&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"a growing proportion of the workforce are digital native and, while they may lack a background in programming, they are well-versed computer and web users and skilled with non-trivial software (e.g. office/mobile applications).  Low-code software engineering aspires to leverage this increasingly computer-savvy workforce"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So which is it as the old PC-raised software application implementers retire and youth replace them?  A bunch of technologically helpless fresh faces or "well-versed and skilled computer users?"&lt;/p&gt;

&lt;h2&gt;
  
  
  Still not enough formal education
&lt;/h2&gt;

&lt;p&gt;As I wrote in "&lt;a href="https://katiekodes.com/what-is-salesforce-flow/#in-defense-of-flow"&gt;In defense of Salesforce Flow&lt;/a&gt;," I strongly believe that computer education for the masses needs to catch up quickly with the explosion of flowchart-based programming languages.&lt;/p&gt;

&lt;p&gt;I want to see more &lt;strong&gt;computer science and software engineering best practice&lt;/strong&gt; books, blogs, and self-help videos that teach intermediate and advanced programming concepts from the 1970's-2000's, but entirely demonstrated in &lt;strong&gt;flowchart-based programming languages&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;I'm horrified that in 2024 with enterprise workers working magic in Salesforce Flow and Microsoft Power Platform, I Googled "low-code software engineering" today and &lt;em&gt;still&lt;/em&gt; didn't find anything useful on old-school software engineering principles.&lt;/p&gt;

&lt;h2&gt;
  
  
  Hope in tablets
&lt;/h2&gt;

&lt;p&gt;Maybe the tablet generation's relative ignorance of certain details about desktop user interfaces is going to help them -- and the educational leaders shepherding them -- avoid missing the forest for the trees as they enter the workforce and become low-code software application developers.&lt;/p&gt;

&lt;p&gt;Maybe teaching the TikTok generation &lt;em&gt;(many of whom have more hands-on-experience-driven intuition about film lighting, reasons to choose a certain type of scene cut, etc. than I learned in 2 semesters of college-level film studies, so I suspect playing around on a tablet has, as Dr. Kolovos suspects, still rendered them a "computer-savvy workforce" at a &lt;strong&gt;business objectives&lt;/strong&gt; level)&lt;/em&gt; about &lt;a href="https://en.wikipedia.org/wiki/Don%27t_repeat_yourself"&gt;"D.R.Y." software application implementation&lt;/a&gt; is going to be the desk job world's 2030's equivalent of teaching the Oregon Trail generation Excel.&lt;/p&gt;

</description>
      <category>softwareengineering</category>
      <category>lowcode</category>
      <category>nocode</category>
      <category>opinion</category>
    </item>
    <item>
      <title>Download every Salesforce object and field definition to JSON</title>
      <dc:creator>Katie</dc:creator>
      <pubDate>Fri, 16 Sep 2022 08:00:00 +0000</pubDate>
      <link>https://dev.to/katiekodes/download-every-salesforce-object-and-field-definition-14kj</link>
      <guid>https://dev.to/katiekodes/download-every-salesforce-object-and-field-definition-14kj</guid>
      <description>&lt;p&gt;I made a new codebase that makes it easy to &lt;a href="https://github.com/kkgthb/download-salesforce-objects-and-fields-as-json"&gt;download the definition of every object and field&lt;/a&gt; in a Salesforce org &lt;em&gt;(part of its "metadata")&lt;/em&gt; onto your hard drive as a JSON file.&lt;/p&gt;

&lt;p&gt;Example usage: If they have programmers on staff who can transform it into a data structure useful to them, your company's data governance team might find such a file useful for keeping a "data dictionary" up-to-date.&lt;/p&gt;

&lt;p&gt;You could send that team a fresh copy of this file every time you alter your Salesforce configuration.&lt;/p&gt;

</description>
      <category>database</category>
      <category>salesforce</category>
    </item>
    <item>
      <title>UNPIVOT to key-value pair in Oracle SQL</title>
      <dc:creator>Katie</dc:creator>
      <pubDate>Thu, 11 Aug 2022 09:00:00 +0000</pubDate>
      <link>https://dev.to/katiekodes/unpivot-to-key-value-pair-in-oracle-sql-5gli</link>
      <guid>https://dev.to/katiekodes/unpivot-to-key-value-pair-in-oracle-sql-5gli</guid>
      <description>&lt;p&gt;I always forget how to use UNPIVOT, and so many documents are focused on numbers data, not generic key-value data. Here’s the thing I actually often need to do.&lt;/p&gt;

&lt;h2&gt;
  
  
  Code
&lt;/h2&gt;

&lt;p&gt;Here’s my source table called &lt;code&gt;source_table&lt;/code&gt;, inside of an Oracle database:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;record_id&lt;/th&gt;
&lt;th&gt;country&lt;/th&gt;
&lt;th&gt;gender&lt;/th&gt;
&lt;th&gt;name_lf&lt;/th&gt;
&lt;th&gt;other_junk&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;123&lt;/td&gt;
&lt;td&gt;Azerbaijan&lt;/td&gt;
&lt;td&gt;F&lt;/td&gt;
&lt;td&gt;Amjit, Anush&lt;/td&gt;
&lt;td&gt;123abc&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;456&lt;/td&gt;
&lt;td&gt;Zimbabwe&lt;/td&gt;
&lt;td&gt;N&lt;/td&gt;
&lt;td&gt;Borges, Benita&lt;/td&gt;
&lt;td&gt;def456&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Here’s the SQL query:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;select&lt;/span&gt;
    &lt;span class="n"&gt;record_id&lt;/span&gt;
    &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;field_key&lt;/span&gt; &lt;span class="c1"&gt;-- Arbitrary naming choice; call this anything you want.&lt;/span&gt;
    &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;field_value&lt;/span&gt; &lt;span class="c1"&gt;-- Arbitrary naming choice; call this anything you want.&lt;/span&gt;
    &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name_lf&lt;/span&gt;
&lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="n"&gt;source_table&lt;/span&gt;
&lt;span class="n"&gt;unpivot&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;field_value&lt;/span&gt; &lt;span class="c1"&gt;-- Arbitrary naming choice; call this anything you want.&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;field_key&lt;/span&gt; &lt;span class="c1"&gt;-- Arbitrary naming choice; call this anything you want.&lt;/span&gt;
    &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;country&lt;/span&gt;
        &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;gender&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And here’s the resultant data:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;record_id&lt;/th&gt;
&lt;th&gt;field_key&lt;/th&gt;
&lt;th&gt;field_value&lt;/th&gt;
&lt;th&gt;name_lf&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;123&lt;/td&gt;
&lt;td&gt;COUNTRY&lt;/td&gt;
&lt;td&gt;Azerbaijan&lt;/td&gt;
&lt;td&gt;Amjit, Anush&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;123&lt;/td&gt;
&lt;td&gt;GENDER&lt;/td&gt;
&lt;td&gt;F&lt;/td&gt;
&lt;td&gt;Amjit, Anush&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;456&lt;/td&gt;
&lt;td&gt;COUNTRY&lt;/td&gt;
&lt;td&gt;Zimbabwe&lt;/td&gt;
&lt;td&gt;Borges, Benita&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;456&lt;/td&gt;
&lt;td&gt;GENDER&lt;/td&gt;
&lt;td&gt;N&lt;/td&gt;
&lt;td&gt;Borges, Benita&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

</description>
      <category>database</category>
      <category>sql</category>
      <category>oracle</category>
    </item>
    <item>
      <title>Check a URL with Selenium IDE</title>
      <dc:creator>Katie</dc:creator>
      <pubDate>Wed, 06 Apr 2022 15:00:00 +0000</pubDate>
      <link>https://dev.to/katiekodes/check-a-url-with-selenium-ide-5di0</link>
      <guid>https://dev.to/katiekodes/check-a-url-with-selenium-ide-5di0</guid>
      <description>&lt;p&gt;It took me a while to figure out how to get &lt;a href="https://www.selenium.dev/selenium-ide/"&gt;Selenium IDE&lt;/a&gt; to click a link, wait for the new tab's page-load to settle down, and validate the URL of the new page, but I did it.&lt;/p&gt;

&lt;p&gt;Overall, I'm &lt;a href="https://katiekodes.com/selenium-ide-check-url/#selenium-ide-caveats"&gt;pretty satisfied&lt;/a&gt; with Selenium IDE.  If you have business processes that involve visiting a web site and clicking around a bunch to "make sure everything looks good," it's a nifty tool for pretending to be yourself, only sped up really really fast.&lt;/p&gt;

&lt;h2&gt;
  
  
  Steps
&lt;/h2&gt;

&lt;p&gt;The one and only test present in this Selenium IDE project runs through 8 steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Open the &lt;a href="https://ko-fi.com/katiekodes"&gt;Katie Kodes&lt;/a&gt; page on Ko-Fi

&lt;ul&gt;
&lt;li&gt;Command:  &lt;code&gt;open&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Target:  &lt;code&gt;katiekodes&lt;/code&gt; &lt;em&gt;(on top of a test base URL of &lt;code&gt;https://ko-fi.com/&lt;/code&gt;)&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Click the &lt;a href="https://katiekodes.com"&gt;Katie Kodes blog&lt;/a&gt; link

&lt;ul&gt;
&lt;li&gt;Command:  &lt;code&gt;click&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Modify new window configuration -&amp;gt; New Window Configuration Enabled:  checked, Window Name:  &lt;code&gt;blog_new_tab&lt;/code&gt;, Timeout:  2000, click "Confirm"&lt;/li&gt;
&lt;li&gt;Target:  &lt;code&gt;xpath=(//a[@target="_blank" and contains(@href, "katiekodes.com")])[1]&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Close the original Ko-Fi tab

&lt;ul&gt;
&lt;li&gt;Command:  &lt;code&gt;close&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Make sure we are viewing the new blog tab

&lt;ul&gt;
&lt;li&gt;Command:  &lt;code&gt;select window&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Target:  &lt;code&gt;handle=${blog_new_tab}&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Wait for something bloggey to be on the screen

&lt;ul&gt;
&lt;li&gt;Command:  &lt;code&gt;wait for element present&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Target:  &lt;code&gt;xpath=(//a[contains(@href, "ko-fi.com")])[1]&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Value:  &lt;code&gt;30000&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;&lt;em&gt;(Technically, this isn't required for this example, but the situation I was dealing with opened a new tab and then handed off cookies through about 4 different URLs before settling down on one, so I decided to validate that things were "all done" by looking for a weird, distinctive HTML element I knew only existed in the final, settled page.)&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Save the blog URL to a variable

&lt;ul&gt;
&lt;li&gt;Command:  &lt;code&gt;execute script&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Target:  &lt;code&gt;return document.URL;&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Value:  &lt;code&gt;theurl&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Assert that the blog URL is correct

&lt;ul&gt;
&lt;li&gt;Command:  &lt;code&gt;assert&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Target:  &lt;code&gt;theurl&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Value:  &lt;code&gt;https://katiekodes.com/&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Close the web browser

&lt;ul&gt;
&lt;li&gt;Command:  &lt;code&gt;close&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Code
&lt;/h2&gt;

&lt;p&gt;To try it yourself, save this code as &lt;code&gt;Selenium Demo.side&lt;/code&gt; on your computer and open it as a project with the &lt;a href="https://www.selenium.dev/selenium-ide/"&gt;Selenium IDE browser plugin&lt;/a&gt;, then click the "Validate the new-tab URL" test and click "Run current test."&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ca2c89aa-50b1-4eea-91e6-c2e01ae6cb0a"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Selenium demo"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://ko-fi.com/"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"tests"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"e363b287-2838-40db-b1b8-57dd100af3a5"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Validate the new-tab URL"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"commands"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"712005e0-c6ec-4f10-9162-da97499d5e23"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"comment"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Open Katie Kodes Ko-Fi donations page"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"open"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"target"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"katiekodes"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"targets"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"9eaf4f01-f179-4c19-855c-4eb9a1968158"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"comment"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Click the Katie Kodes blog link"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"click"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"target"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"xpath=(//a[@target=&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;_blank&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt; and contains(@href, &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;katiekodes.com&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;)])[1]"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"targets"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"opensWindow"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"windowHandleName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"blog_new_tab"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"windowTimeout"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2000&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"3c0233e1-b2d4-4c82-b806-7d9133e94e96"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"comment"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Close the original Ko-Fi tab"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"close"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"target"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"targets"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"5683db68-8b78-48a7-b959-84ebccd70119"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"comment"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Make sure we are viewing the new blog tab"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"selectWindow"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"target"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"handle=${blog_new_tab}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"targets"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"a37060a8-8e9b-4848-9068-f4a1fcb5f2ca"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"comment"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Wait for something bloggey to be on the screen"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"waitForElementPresent"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"target"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"xpath=(//a[contains(@href, &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;ko-fi.com&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;)])[1]"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"targets"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"30000"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ff897cc8-d4f0-4762-8695-d9551d7f4e96"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"comment"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Save the blog URL to a variable"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"executeScript"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"target"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"return document.URL;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"targets"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"theurl"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"b3b8f50b-4266-4c68-902b-33e150279274"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"comment"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Assert that the blog URL is correct"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"assert"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"target"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"theurl"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"targets"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://katiekodes.com/"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"68c8b88e-84bb-4c80-b914-3a0278995967"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"comment"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Close the web browser"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"close"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"target"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"targets"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"suites"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"398fd234-8bcf-48ff-ab6c-4785b1ab469f"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"My first suite"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"persistSession"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"parallel"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"timeout"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"tests"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"e363b287-2838-40db-b1b8-57dd100af3a5"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"urls"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"https://ko-fi.com/"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"plugins"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

</description>
      <category>selenium</category>
      <category>testing</category>
      <category>tutorial</category>
      <category>webdev</category>
    </item>
    <item>
      <title>SvelteKit Minimum Viable Build</title>
      <dc:creator>Katie</dc:creator>
      <pubDate>Mon, 10 Jan 2022 17:00:00 +0000</pubDate>
      <link>https://dev.to/katiekodes/sveltekit-minimum-viable-build-1g2j</link>
      <guid>https://dev.to/katiekodes/sveltekit-minimum-viable-build-1g2j</guid>
      <description>&lt;p&gt;I’m wondering if SvelteKit could make it easy for me to build a UI onto an app to help me write “runbooks” for operational processes at work that happen every few weeks. So, first I have to figure out what goes in a SvelteKit, and as usual, I’m starting as bare-bones as the system will let me.&lt;/p&gt;

&lt;h2&gt;
  
  
  Process
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Get a &lt;a href="https://www.netlify.com/"&gt;Netlify.com&lt;/a&gt; free account&lt;/li&gt;
&lt;li&gt;Set up a Netlify.com site, connected to a GitHub &lt;a href="https://github.com/kkgthb/web-site-sveltekit-01-min-viable-build"&gt;repository&lt;/a&gt;, that contains just 4 files: 

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;/src/routes/index.svelte&lt;/code&gt; * &lt;code&gt;/src/app.html&lt;/code&gt; * &lt;code&gt;/svelte.config.js&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;/package.json&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;TEST IT:&lt;/strong&gt; Make sure you can visit &lt;code&gt;https://your-site.netlify.app/&lt;/code&gt; as expected, without “page not found” errors.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;To do: Profit&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Magic words
&lt;/h2&gt;

&lt;p&gt;SvelteKit has a “&lt;a href="https://dev.to/katiekodes/how-to-break-and-rebuild-the-jamstack-2g24"&gt;magic&lt;/a&gt; folder” path of &lt;code&gt;/src/routes/&lt;/code&gt; &lt;em&gt;(&lt;a href="https://kit.svelte.dev/docs#routing-pages"&gt;documentation&lt;/a&gt;)&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;As I mentioned for Next.js, &lt;a href="https://dev.to/katiekodes/what-is-a-static-site-generator-350o"&gt;static site generator&lt;/a&gt; world, “ &lt;strong&gt;routing&lt;/strong&gt; ” tends to refer to the ways you can configure the SSG to turn data you’re feeding it into actual URLs. Most of them have some way of automatically doing “routing” based on the way you named data folders or files, or the way you named template folders or files. Some of them will pretty much eat every folder they can get their hands on and try to route it &lt;em&gt;(11ty)&lt;/em&gt;; &lt;a href="https://kit.svelte.dev/docs#routing-pages"&gt;others like SvelteKit seem to favor limiting this behavior, by default, to folders with “magic names” like &lt;code&gt;/routes/&lt;/code&gt;&lt;/a&gt; – and then there are some more advanced syntaxes for doing fancier “routing” like looping over a bunch of Markdown files in your codebase and turning them into URLs.&lt;/p&gt;




&lt;h2&gt;
  
  
  Files
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;/src/routes/index.svelte&lt;/code&gt;
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;(“&lt;a href="https://kit.svelte.dev/docs#routing-pages"&gt;The filename determines the route. For example, &lt;code&gt;src/routes/index.svelte&lt;/code&gt; is the root of your site.&lt;/a&gt;“)&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;Hello world!&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;code&gt;/src/app.html&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Unlike Next.js and Gatsby, SvelteKit won’t implicitly write pages’ outer HTML for you.&lt;/p&gt;

&lt;p&gt;By default, that means creating an HTML file at &lt;code&gt;/src/app.html&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"en"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;charset=&lt;/span&gt;&lt;span class="s"&gt;"utf-8"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"viewport"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"width=device-width, initial-scale=1"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
        %svelte.head%
    &lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
        %svelte.body%
    &lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;code&gt;/svelte.config.js&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;To develop locally, &lt;a href="https://kit.svelte.dev/docs#configuration"&gt;you can export an empty object&lt;/a&gt;, but you have to have this file, and the moment you want to deploy your site to a host in the cloud like Netlify, you’ll need to start filling it out, so that you can tell Sveltekit to give the cloud builder some extra information that it needs.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;adapter&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@sveltejs/adapter-auto&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;kit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;adapter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;adapter&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;code&gt;/package.json&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Note the &lt;code&gt;"type": "module"&lt;/code&gt; property. Best I can tell, this makes sure the &lt;code&gt;import&lt;/code&gt; syntax at the top of the config file works properly.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;(Also, it seems to be a known issue that you’ll get errors if you try to use &lt;code&gt;devDependencies&lt;/code&gt; instead of &lt;code&gt;dependencies&lt;/code&gt; on Windows.)&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"sveltekit-mvb"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"0.0.1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"scripts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"dev"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"svelte-kit dev"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"build"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"svelte-kit build"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"module"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"dependencies"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"@sveltejs/adapter-auto"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"next"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"@sveltejs/kit"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"next"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"svelte"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"next"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Output
&lt;/h2&gt;

&lt;p&gt;The resulting page has the following HTML:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"en"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;charset=&lt;/span&gt;&lt;span class="s"&gt;"utf-8"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"viewport"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"width=device-width, initial-scale=1"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;

        &lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"stylesheet"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"/_app/assets/start-aaaaaa1.css"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"modulepreload"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"/_app/start-bbbbbb2.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"modulepreload"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"/_app/chunks/vendor-cccccc3.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"modulepreload"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"/_app/layout.svelte-dddddd4.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"modulepreload"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"/_app/pages/index.svelte-eeeeee5.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

        &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"module"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;start&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/_app/start-bbbbbb2.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="nx"&gt;start&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
                &lt;span class="na"&gt;target&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="na"&gt;paths&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;base&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;assets&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
                &lt;span class="na"&gt;session&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt;
                &lt;span class="na"&gt;route&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="na"&gt;spa&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="na"&gt;trailing_slash&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;never&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="na"&gt;hydrate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="na"&gt;nodes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
                        &lt;span class="k"&gt;import&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/_app/layout.svelte-dddddd4.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                        &lt;span class="k"&gt;import&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/_app/pages/index.svelte-eeeeee5.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                    &lt;span class="p"&gt;],&lt;/span&gt;
                    &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;URL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://your-site.netlify.app/&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                    &lt;span class="na"&gt;params&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;});&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;


&lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;Hello world!&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Like with Gatsby and Next.js output, there’s a lot of JavaScript embedded in my page, but the &lt;code&gt;&amp;lt;div&amp;gt;Hello world!&amp;lt;/div&amp;gt;&lt;/code&gt; I expect to see exists deep in the middle.&lt;/p&gt;




&lt;h2&gt;
  
  
  Helpful links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/kkgthb/web-site-sveltekit-01-min-viable-build"&gt;This codebase on GitHub&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>jamstack</category>
      <category>webdev</category>
      <category>sveltekit</category>
    </item>
    <item>
      <title>Salesforce Apex lets you use external IDs</title>
      <dc:creator>Katie</dc:creator>
      <pubDate>Tue, 04 Jan 2022 00:00:00 +0000</pubDate>
      <link>https://dev.to/katiekodes/salesforce-apex-lets-you-use-external-ids-19dk</link>
      <guid>https://dev.to/katiekodes/salesforce-apex-lets-you-use-external-ids-19dk</guid>
      <description>&lt;p&gt;How did I miss this?  &lt;a href="https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/langCon_apex_dml_foreign_keys.htm"&gt;Salesforce Apex lets you DML lookup and master-detail relationships by external ID.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is huge for actually letting me leverage the &lt;a href="https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_classes_annotation_testsetup.htm"&gt;performance benefits of &lt;code&gt;@testSetup&lt;/code&gt;&lt;/a&gt; and not worry about the fact that it &lt;a href="https://salesforce.stackexchange.com/questions/160328/what-are-the-advantage-of-the-testsetup-annotation"&gt;doesn't let you see IDs of records you used it to DML without a SOQL query&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@isTest&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;WowThisWorks&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="nd"&gt;@testSetup&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;insertSampleData&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;Lowest__c&lt;/span&gt; &lt;span class="n"&gt;l&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Lowest__c&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;External_ID__c&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="no"&gt;L01&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="no"&gt;L&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="no"&gt;INSERT&lt;/span&gt; &lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

        &lt;span class="n"&gt;Middle__c&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Middle__c&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;External_ID__c&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="no"&gt;M01&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="no"&gt;M&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Lowest__c&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Id&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="no"&gt;INSERT&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="n"&gt;testMethod&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;runTest01&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;Middle__c&lt;/span&gt; &lt;span class="n"&gt;mFake&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Middle__c&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;External_ID__c&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="no"&gt;M01&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// THIS IS THE MAGIC&lt;/span&gt;

        &lt;span class="n"&gt;Highest__c&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Highest__c&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="no"&gt;H&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Middle__r&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;mFake&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// NOTE THE __r INSTEAD OF __C&lt;/span&gt;

        &lt;span class="nc"&gt;Test&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;startTest&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="no"&gt;INSERT&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="nc"&gt;Test&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;stopTest&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

        &lt;span class="n"&gt;Highest__c&lt;/span&gt; &lt;span class="n"&gt;hAfter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;
            &lt;span class="no"&gt;SELECT&lt;/span&gt; &lt;span class="nc"&gt;Name&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; 
            &lt;span class="n"&gt;Middle__r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Name&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; 
            &lt;span class="n"&gt;hAfter&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Middle__r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Lower__r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Name&lt;/span&gt; 
            &lt;span class="no"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;Highest__c&lt;/span&gt; 
            &lt;span class="no"&gt;LIMIT&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
        &lt;span class="o"&gt;];&lt;/span&gt;
        &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;concat&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;hAfter&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Name&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="err"&gt;'&lt;/span&gt; &lt;span class="o"&gt;~~&lt;/span&gt; &lt;span class="err"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;hAfter&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Middle__r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Name&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="err"&gt;'&lt;/span&gt; &lt;span class="o"&gt;~~&lt;/span&gt; &lt;span class="err"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;hAfter&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Middle__r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Lower__r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Name&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;assertEquals&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="no"&gt;H&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;~~&lt;/span&gt; &lt;span class="no"&gt;M&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;~~&lt;/span&gt; &lt;span class="no"&gt;L&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;concat&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I've got many, many &lt;a href="http://etutorials.org/SQL/Database+design+for+mere+mortals/Part+II+The+Design+Process/Chapter+11.+Business+Rules/Validation+Tables/"&gt;validation tables&lt;/a&gt; that Contact can point to, all of which feed into a trigger I need to write tests for.  They all have unique required external IDs built into their schemas.&lt;/p&gt;

&lt;p&gt;It's going to be amazing to be able to create test-data &lt;strong&gt;Contact&lt;/strong&gt; records that look up these "validation table" records by their external IDs without using up any SOQL queries or caching the "validation table" records in memory in test classes.&lt;/p&gt;

&lt;p&gt;Happy new year to me!&lt;/p&gt;

</description>
      <category>salesforce</category>
    </item>
    <item>
      <title>Localhost HTML with Python on Windows</title>
      <dc:creator>Katie</dc:creator>
      <pubDate>Tue, 09 Nov 2021 15:00:00 +0000</pubDate>
      <link>https://dev.to/katiekodes/localhost-html-with-python-on-windows-3k6a</link>
      <guid>https://dev.to/katiekodes/localhost-html-with-python-on-windows-3k6a</guid>
      <description>&lt;p&gt;If you’ve ever tried to open a file &lt;code&gt;c:\example\my_web_page.html&lt;/code&gt; in a web browser by putting &lt;code&gt;file:///C:/example/webserver/my_web_page.html&lt;/code&gt;, you might have noticed that HTML &lt;code&gt;&amp;lt;FORM&amp;gt;...&amp;lt;/FORM&amp;gt;&lt;/code&gt; tags don’t work like they’re supposed to.&lt;/p&gt;

&lt;p&gt;To get an HTML form’s submit button to actually work, you need to visit &lt;code&gt;my_web_page.html&lt;/code&gt; at a &lt;code&gt;http://localhost/&lt;/code&gt;-style URL, not a &lt;code&gt;file:///C:/&lt;/code&gt;-style URL.&lt;/p&gt;

&lt;p&gt;On Windows, with the help of Python, you can do this.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;(You can see that the submit button does nothing when using a &lt;code&gt;file:///C:/&lt;/code&gt;-style URL by opening your browser’s developer tools, going to the Network tab, and clicking the button. Nothing new appears, even though you’d expect &lt;a href="https://katiekodes.com/http-intro/#2---method"&gt;a &lt;code&gt;GET&lt;/code&gt; request&lt;/a&gt; to appear in the logs.)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Here’s the content of my file &lt;code&gt;c:\example\my_web_page.html&lt;/code&gt; that refuses to work locally:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;html&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;http-equiv=&lt;/span&gt;&lt;span class="s"&gt;"content-type"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"text/html; charset=utf-8"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"icon"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2016%2016'%3E%3Ctext%20x='0'%20y='14'%3E❓%3C/text%3E%3C/svg%3E"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"image/svg+xml"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;I'm a little web page&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;I'm a little web page&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;short and stout&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;hr&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;form&lt;/span&gt; &lt;span class="na"&gt;method=&lt;/span&gt;&lt;span class="s"&gt;"get"&lt;/span&gt; &lt;span class="na"&gt;action=&lt;/span&gt;&lt;span class="s"&gt;"/the_confirmation_page.html"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"radio"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"form_yes"&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"yesno_answer"&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"yes"&lt;/span&gt; &lt;span class="na"&gt;required&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;label&lt;/span&gt; &lt;span class="na"&gt;for=&lt;/span&gt;&lt;span class="s"&gt;"yesno_answer"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Yes&lt;span class="nt"&gt;&amp;lt;/label&amp;gt;&amp;lt;br&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"radio"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"form_no"&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"yesno_answer"&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"no"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;label&lt;/span&gt; &lt;span class="na"&gt;for=&lt;/span&gt;&lt;span class="s"&gt;"yesno_answer"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;No&lt;span class="nt"&gt;&amp;lt;/label&amp;gt;&amp;lt;br&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"radio"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"form_maybe"&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"yesno_answer"&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"maybe"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;label&lt;/span&gt; &lt;span class="na"&gt;for=&lt;/span&gt;&lt;span class="s"&gt;"form_maybe"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Maybe&lt;span class="nt"&gt;&amp;lt;/label&amp;gt;&amp;lt;br&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&amp;lt;br&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"submit"&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"Submit"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/form&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;hr/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--P5GQPbTC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://katiekodes.com/images/screenshots/screenshot-localhost-html-python-2021-11/file-homepage.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--P5GQPbTC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://katiekodes.com/images/screenshots/screenshot-localhost-html-python-2021-11/file-homepage.png" alt="Screenshot of the home page accessed as a file in a browser" width="459" height="323"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And here’s the content of my file &lt;code&gt;c:\example\the_confirmation_page.html&lt;/code&gt;. This is a second web page where I’d like the first web page to send my “yes/no/maybe” choice whenever I click the submit button.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;html&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;http-equiv=&lt;/span&gt;&lt;span class="s"&gt;"content-type"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"text/html; charset=utf-8"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"icon"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2016%2016'%3E%3Ctext%20x='0'%20y='14'%3E☑️%3C/text%3E%3C/svg%3E"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"image/svg+xml"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;What you chose&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;urlSearchParams&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;URLSearchParams&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;search&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;params&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fromEntries&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;urlSearchParams&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;entries&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;get_h1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!!&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;!!&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;yesno_answer&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s2"&gt;`I'm so happy you were able to make up your mind that your answer is "&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;yesno_answer&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]}&lt;/span&gt;&lt;span class="s2"&gt;."`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Looks like you couldn't make up your mind.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;};&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fill_in_h1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;fill_me_in&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;innerHTML&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;get_h1&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="p"&gt;};&lt;/span&gt;
      &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;fill_in_h1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;h1&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"fill_me_in"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--K4-UF9bc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://katiekodes.com/images/screenshots/screenshot-localhost-html-python-2021-11/file-confpage.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--K4-UF9bc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://katiekodes.com/images/screenshots/screenshot-localhost-html-python-2021-11/file-confpage.png" alt="Screenshot of the confirmation page accessed as a file in a browser" width="880" height="117"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You might notice that if you visit &lt;code&gt;file:///C:/example/the_confirmation_page.html?yesno_answer=maybe&lt;/code&gt; and play with the value of &lt;code&gt;yesno_answer&lt;/code&gt; in the URL, everything works as expected.&lt;/p&gt;

&lt;p&gt;It’s not the JavaScript in the confirmation page that doesn’t work with &lt;code&gt;file:///C:/&lt;/code&gt;-style URLs.&lt;/p&gt;

&lt;p&gt;It’s literally just getting the submit button to work in &lt;code&gt;my_web_page.html&lt;/code&gt;’s &lt;code&gt;&amp;lt;FORM&amp;gt;...&amp;lt;/FORM&amp;gt;&lt;/code&gt; that’s the problem.&lt;/p&gt;

&lt;p&gt;To get the submit button in &lt;code&gt;my_web_page.html&lt;/code&gt; to work, you have to deliver it to your web browser at an actual URL starting with &lt;code&gt;http://&lt;/code&gt;. Which means you have to put it on a web server.&lt;/p&gt;

&lt;p&gt;Luckily, with Python, you can run a web server on your own computer, and you don’t even need administrator rights to the computer.&lt;/p&gt;

&lt;h2&gt;
  
  
  Python prerequisites
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;You need to get all the way through the “Using our IDE to program” part of my article “&lt;a href="https://dev.to/katiekodes/setting-up-windows-store-python-with-pandas-in-vscode-23g2"&gt;Setting up Windows Store Python with Pandas in VSCode&lt;/a&gt;” &lt;em&gt;(or have installed Python your own way)&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;You need to be comfortable running a script called &lt;code&gt;c:\example\hello.py&lt;/code&gt; whose source code is &lt;code&gt;print('Hello World')&lt;/code&gt; on your computer and validating that you see your computer say “ &lt;strong&gt;Hello World&lt;/strong&gt; ” to you in the script execution environment’s “system output.”&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Code the web server
&lt;/h2&gt;

&lt;p&gt;Once you know how to create and run Python files, create one at &lt;code&gt;c:\some_other_folder\webserver.py&lt;/code&gt;. I chose a folder called “some_other_folder” to demonstrate that the Python script and the HTML files don’t have to live in the same place on your computer.&lt;/p&gt;

&lt;p&gt;Its contents should be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Credit to Max Shvedov at https://stackoverflow.com/questions/51189628/simple-http-server-in-python-how-to-get-files-from-dir-path
# Forgot where else I picked up code
&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;http.server&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;socketserver&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;os&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt;

&lt;span class="n"&gt;my_host_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;'localhost'&lt;/span&gt;
&lt;span class="n"&gt;my_port&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;8888&lt;/span&gt;
&lt;span class="n"&gt;my_html_folder_path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;'c:&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s"&gt;example&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s"&gt;'&lt;/span&gt;

&lt;span class="n"&gt;my_home_page_file_path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;'my_web_page.html'&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyHttpRequestHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SimpleHTTPRequestHandler&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;_set_headers&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;send_response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;send_header&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'Content-Type'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'text/html'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;send_header&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'Content-Length'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getsize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getPath&lt;/span&gt;&lt;span class="p"&gt;()))&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;end_headers&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;getPath&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;'/'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;content_path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="n"&gt;my_html_folder_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;my_home_page_file_path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;content_path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;my_html_folder_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'?'&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:])&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;content_path&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;getContent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;content_path&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nb"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;content_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mode&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;'r'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;encoding&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;'utf-8'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;bytes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'utf-8'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;do_GET&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_set_headers&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;wfile&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getContent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getPath&lt;/span&gt;&lt;span class="p"&gt;()))&lt;/span&gt;

&lt;span class="n"&gt;my_handler&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;MyHttpRequestHandler&lt;/span&gt;

&lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;socketserver&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TCPServer&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;my_port&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;my_handler&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;httpd&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Http Server Serving at port"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;my_port&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;httpd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;serve_forever&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Start and stop the web server
&lt;/h2&gt;

&lt;p&gt;Run the script &lt;em&gt;(“Run Python File in Terminal”, if using the VSCode play button in the upper right corner)&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--X2b2CliL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://katiekodes.com/images/screenshots/screenshot-localhost-html-python-2021-11/run-python.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--X2b2CliL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://katiekodes.com/images/screenshots/screenshot-localhost-html-python-2021-11/run-python.png" alt="Screenshot of the run button in VSCode" width="701" height="452"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If &lt;strong&gt;Windows Firewall&lt;/strong&gt; pops up a dialog box, un-check all the checkboxes and click &lt;strong&gt;Cancel&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Cqou87zR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://katiekodes.com/images/screenshots/screenshot-localhost-html-python-2021-11/firewall.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Cqou87zR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://katiekodes.com/images/screenshots/screenshot-localhost-html-python-2021-11/firewall.png" alt="Screenshot of Windows Firewall dialog box" width="538" height="429"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the “ &lt;strong&gt;Terminal&lt;/strong&gt; ” tab of a panel below your code, you should see the words:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Http Server Serving at port 8888
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It should appear below a command prompt that says:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;PS C:\Users\YOUR_USERNAME&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--D73x1yX5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://katiekodes.com/images/screenshots/screenshot-localhost-html-python-2021-11/python-running.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--D73x1yX5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://katiekodes.com/images/screenshots/screenshot-localhost-html-python-2021-11/python-running.png" alt="Screenshot of a running server in VSCode" width="748" height="518"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Note that unlike the &lt;code&gt;print('Hello World')&lt;/code&gt; script, this one won’t have a trailing &lt;code&gt;PS C:\Users\YOUR_USERNAME&amp;gt;&lt;/code&gt; &lt;em&gt;after&lt;/em&gt; the program’s output.&lt;/p&gt;

&lt;p&gt;That’s because the Python program is still running! A web server wouldn’t be very useful if it didn’t run all the time and wait around for people to visit its web pages.&lt;/p&gt;

&lt;p&gt;To stop the Python code from running, click in the &lt;strong&gt;Terminal&lt;/strong&gt; pane at the bottom of VSCode and do a &lt;strong&gt;Ctrl&lt;/strong&gt; + &lt;strong&gt;C&lt;/strong&gt; combination on your keyboard &lt;em&gt;(yes, I know that’s usually “copy” in Windows)&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;In the terminal output, there will be a bunch of text starting with the word “Traceback” and ending with the word “KeyboardInterrupt.” Most importantly, though, you’ll see that you’re back at a fresh &lt;code&gt;PS C:\Users\YOUR_USERNAME&amp;gt;&lt;/code&gt; command prompt as the last thing in the terminal.&lt;/p&gt;

&lt;p&gt;If for any reason you can’t get this to work, right-click on your Windows taskbar, click &lt;strong&gt;Task Manager&lt;/strong&gt; , click the &lt;strong&gt;Details&lt;/strong&gt; tab, sort the &lt;strong&gt;Name&lt;/strong&gt; column &lt;em&gt;(the first one)&lt;/em&gt; alphabetically by clicking on its heading, and scroll down into the P’s looking for a &lt;code&gt;.exe&lt;/code&gt; starting with the word “python.” Right-click it and click &lt;strong&gt;End task&lt;/strong&gt; , then &lt;strong&gt;End process&lt;/strong&gt; in the confirmation popup. Close out of Task Manager and head back to VSCode. You should see a fresh &lt;code&gt;PS C:\Users\YOUR_USERNAME&amp;gt;&lt;/code&gt; prompt at the end of your terminal output, although without the &lt;code&gt;Tracebak...KeyboardInterrupt&lt;/code&gt; content.&lt;/p&gt;

&lt;h2&gt;
  
  
  Visit your web page
&lt;/h2&gt;

&lt;p&gt;Now that you know how to start and stop the web server, run the Python script in the terminal again to start it.&lt;/p&gt;

&lt;p&gt;Open Firefox and visit &lt;code&gt;http://localhost:8888&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;(I seem to have written sample Python code that gets into an infinite loop, waiting for the web page to load, with Chrome. Not sure why. Sorry.)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;If you’d like, open up the web browser’s developer tools &lt;em&gt;( &lt;strong&gt;Ctrl&lt;/strong&gt; + &lt;strong&gt;Shift&lt;/strong&gt; + &lt;strong&gt;i&lt;/strong&gt; )&lt;/em&gt; and click on the “ &lt;strong&gt;Network&lt;/strong&gt; ” tab, making sure that under the gear-shaped settings icon at right, “ &lt;strong&gt;Persist Logs&lt;/strong&gt; ” is checked.&lt;/p&gt;

&lt;p&gt;Pick one of the radio buttons and click &lt;strong&gt;Submit&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Now your web browser should take you to &lt;code&gt;http://localhost:8888/the_confirmation_page.html?yesno_answer=yes&lt;/code&gt; &lt;em&gt;(or “no” or “maybe” at the end, depending what you picked)&lt;/em&gt; – you’ll see the URL bar has changed – and the web page should tell you it’s so happy you picked “yes” &lt;em&gt;(or “no” or “maybe”)&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;If you were watching the developer tools Network tab, you should see that you made a request with a method of &lt;code&gt;GET&lt;/code&gt; to a domain of &lt;code&gt;localhost:8888&lt;/code&gt; and a file of &lt;code&gt;the_confirmation_page.html?yesno_answer=yes&lt;/code&gt; &lt;em&gt;(or “no” or “maybe”)&lt;/em&gt;, and that the response’s status code was &lt;code&gt;200&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Back in VSCode, you’ll see two more lines below &lt;code&gt;Http Server Serving at port 8888&lt;/code&gt;, followed by the outlined box that indicates your Python program is still running:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;127.0.0.1&lt;/code&gt; &lt;em&gt;(or some other IP address)&lt;/em&gt; &lt;code&gt;- - [&lt;/code&gt; &lt;em&gt;(a timestamp)&lt;/em&gt; &lt;code&gt;] "GET / HTTP/1.1" 200 -&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;127.0.0.1&lt;/code&gt; &lt;em&gt;(or some other IP address)&lt;/em&gt; &lt;code&gt;- - [&lt;/code&gt; &lt;em&gt;(a timestamp)&lt;/em&gt; &lt;code&gt;] "GET /the_confirmation_page.html?yesno_answer=maybe HTTP/1.1" 200 -&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--riaLO-Gf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://katiekodes.com/images/screenshots/screenshot-localhost-html-python-2021-11/python-visiting-pages.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--riaLO-Gf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://katiekodes.com/images/screenshots/screenshot-localhost-html-python-2021-11/python-visiting-pages.png" alt="Screenshot of a running server in VSCode with page visit logs" width="880" height="426"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Clean up
&lt;/h2&gt;

&lt;p&gt;Don’t forget to stop your web server with &lt;strong&gt;Ctrl+C&lt;/strong&gt; in the VSCode terminal.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;(It doesn’t work if the last part of VSCode you clicked into was the code editor – the key combination is just plain old “copy” up there.)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;You’ll see a fresh &lt;code&gt;PS C:\Users\YOUR_USERNAME&amp;gt;&lt;/code&gt; prompt at the end of your terminal output when you’ve successfully stopped your server.&lt;/p&gt;

&lt;h2&gt;
  
  
  Code your web page
&lt;/h2&gt;

&lt;p&gt;I’ll leave the hard part up to you – actually coding &lt;code&gt;my_web_page.html&lt;/code&gt; and &lt;code&gt;the_confirmation_page.html&lt;/code&gt; to do whatever it was you wanted to test!&lt;/p&gt;

</description>
      <category>python</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Jekyll doesn’t do components? Liar!</title>
      <dc:creator>Katie</dc:creator>
      <pubDate>Thu, 09 Sep 2021 15:00:00 +0000</pubDate>
      <link>https://dev.to/katiekodes/jekyll-doesnt-do-components-liar-10bb</link>
      <guid>https://dev.to/katiekodes/jekyll-doesnt-do-components-liar-10bb</guid>
      <description>&lt;p&gt;Hot take: anyone who tells you that Jekyll doesn’t support component-based design, and that you need a React- or Vue-based &lt;a href="https://dev.to/katiekodes/what-is-a-static-site-generator-350o"&gt;static site generator&lt;/a&gt;, is wrong.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Any basic fragment-of-HTML “component” you can define with JSX in a file and then cross-reference as &lt;code&gt;&amp;lt;MyComponent key="value" /&amp;gt;&lt;/code&gt;, you can just as easily define with Liquid in a file and cross-reference in Jekyll as &lt;code&gt;{% include MyComponent.html key=value %}&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Any basic fragment-of-HTML “layout” you can define with JSX in a file and then cross-reference as &lt;code&gt;&amp;lt;MyLayout&amp;gt;Hello, world&amp;lt;/MyLayout&amp;gt;&lt;/code&gt;, you can just as easily define with Liquid in a file and then cross-reference in the front matter of a Jekyll template as &lt;code&gt;layout: MyLayout&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Example
&lt;/h2&gt;

&lt;p&gt;Remember my “what you see is what you get” &lt;a href="https://dev.to/katiekodes/gatsby-react-wsyiwyg-cms-friendly-markdown-1npm"&gt;&lt;em&gt;(“WYSIWYG”)&lt;/em&gt; componentized Squarespace-style “site builder”&lt;/a&gt; I learned Gatsby so I could build last year?&lt;/p&gt;

&lt;p&gt;I didn’t actually need Gatsby – here’s the &lt;a href="https://github.com/kkgthb/web-site-jekyll-03-wysiwyg"&gt;source code in Jekyll&lt;/a&gt;, and ta-da, &lt;a href="https://jekyll-wysiwyg-site-builder.netlify.app/"&gt;live site&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--oXhNplkH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://katiekodes.com/images/header-gatsby-movable.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--oXhNplkH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://katiekodes.com/images/header-gatsby-movable.png" alt="Screenshot of a basic componentized site, before and after editing" width="880" height="469"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Drag-and-drop
&lt;/h3&gt;

&lt;p&gt;Need to see with your own eyes that it can have a drag-and-drop CMS experience? &lt;a href="https://app.stackbit.com/create?theme=https://github.com/kkgthb/web-site-jekyll-03-wysiwyg"&gt;Click around this theme in Stackbit and see.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://app.stackbit.com/create?theme=https://github.com/kkgthb/web-site-jekyll-03-wysiwyg"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--dROCwOgW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://assets.stackbit.com/badge/create-with-stackbit.svg" alt="Create with Stackbit" width="216" height="36"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Jekyll isn’t perfect
&lt;/h2&gt;

&lt;p&gt;Okay, actually, no one’s &lt;em&gt;wrong&lt;/em&gt;, per se, and certainly not &lt;em&gt;lying&lt;/em&gt;, about newer SSGs &lt;em&gt;(and their templating languages)&lt;/em&gt; helping you develop components easily.&lt;/p&gt;

&lt;p&gt;I just wanted to point out that componentizing a site so that you can give content authors a Wix-like drag-and-drop experience comes from:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;architecting a data model for that purpose&lt;/li&gt;
&lt;li&gt;architecting your static site generator templating for that purpose&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You don’t need a JavaScript-based SSG or a “hydrating” SSG or a “modern” SSG or anything of the sort to do really fancy things with “components.”&lt;/p&gt;

&lt;p&gt;“Components” are a &lt;strong&gt;way of thinking&lt;/strong&gt; , not a property of a specific SSG templating language.&lt;/p&gt;

&lt;p&gt;However, there are some &lt;em&gt;related&lt;/em&gt; problems you might run into like:&lt;/p&gt;

&lt;h3&gt;
  
  
  The syntax can be heavy
&lt;/h3&gt;

&lt;p&gt;Liquid doesn’t &lt;em&gt;really&lt;/em&gt; love objects &amp;amp; arrays – particularly not making it easy to instantiate them as literals.&lt;/p&gt;

&lt;p&gt;As soon as you want to pass around particularly complicated structured data, or do any fancy preprocessing of it, the amount of Liquid that you have to write really starts to explode, compared to the amount of JSX or Vue.js templating code &lt;em&gt;(which JavaScript – including NPM package imports – slips right into natively)&lt;/em&gt; that you have to write.&lt;/p&gt;

&lt;h4&gt;
  
  
  But also, the syntax can be light
&lt;/h4&gt;

&lt;p&gt;That said, when you &lt;em&gt;don’t&lt;/em&gt; have heavy computation to do, I find Liquid’s plain-HTML-like syntax &lt;em&gt;much&lt;/em&gt; cleaner and more concise than React’s or Vue’s templating syntaxes, which is why I’m defending Jekyll in the first place.&lt;/p&gt;

&lt;p&gt;Here’s what a basic component looks like in React:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;Home&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Hello world!&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here’s what that same component looks like in Liquid:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;Hello world!&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The Jekyll ecosystem is small
&lt;/h3&gt;

&lt;h4&gt;
  
  
  It’s not JavaScript all the way down
&lt;/h4&gt;

&lt;p&gt;When you’re using Jekyll, any custom &lt;em&gt;computation&lt;/em&gt; you need that exceeds the power of Shopify’s Liquid templating language has to be defined in the Ruby programming language.&lt;/p&gt;

&lt;p&gt;I’ll admit, it’s really nice to use &lt;strong&gt;one&lt;/strong&gt; programming language – JavaScript – in:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The front-end code you deliver to site visitors’ browsers alongside your HTML and CSS &lt;em&gt;(in Jekyll, that’s JavaScript)&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;The HTML templating code &lt;em&gt;(in Jekyll, that’s Liquid)&lt;/em&gt;. 

&lt;ul&gt;
&lt;li&gt;Jekyll &lt;em&gt;won’t&lt;/em&gt; let you randomly call Ruby’s &lt;code&gt;.map{}&lt;/code&gt; within Liquid template code. You have hand-add Ruby code to the Liquid specification as a “Liquid filter” using Jekyll’s “plugins” functionality.&lt;/li&gt;
&lt;li&gt;React/Vue-based SSGs, however, &lt;em&gt;will&lt;/em&gt; let you randomly call JavaScript’s &lt;code&gt;.map()&lt;/code&gt; within their templating languages, because it’s built into the syntax of the templating languages themselves that you’re allowed to do that.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Deep-back-end functionality &lt;em&gt;(in Jekyll, that’s Ruby)&lt;/em&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  NPM &amp;gt; Gems
&lt;/h4&gt;

&lt;p&gt;Let’s be honest, these days all the cool stuff – particularly for supporting web site generation – is an NPM package, not a Ruby Gem. Like libraries that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.npmjs.com/package/@sanity/client"&gt;Import content from Sanity CMS&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Render front-end HTML &amp;amp; CSS &amp;amp; JavaScript that &lt;a href="https://www.npmjs.com/package/react-player"&gt;embeds a video player into your web site&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Content editing tools are scarce
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Headless CMS is tough
&lt;/h4&gt;

&lt;p&gt;Jekyll is old, and it doesn’t bake in a presumption that you’ll be fetching external API-based headless CMS data into your build the way Eleventy does.&lt;/p&gt;

&lt;p&gt;To use data from Sanity, Contentful, the Notion API, the Wordpress API, etc. you literally have to run &lt;em&gt;(and possibly hand-write)&lt;/em&gt; code that dumps API-sourced data into files on your filesystem that Jekyll &lt;em&gt;can&lt;/em&gt; understand, &lt;em&gt;before&lt;/em&gt; running &lt;code&gt;jekyll build&lt;/code&gt;. &lt;em&gt;(A couple of pre-written libraries: &lt;a href="https://github.com/contentful/jekyll-contentful-data-import"&gt;jekyll-contentful-data-import&lt;/a&gt;, &lt;a href="https://github.com/stackbit/sourcebit"&gt;Sourcebit&lt;/a&gt;.)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;You can 100% build a really well-componentized theme in Liquid, as I’ve shown above. But the whole point of building a componentized theme is to give people a Wix-like experience through a drag-and-drop &lt;a href="https://en.wikipedia.org/wiki/Graphical_user_interface"&gt;GUI&lt;/a&gt; editor, and most of the &lt;a href="https://dev.to/katiekodes/choosing-a-headless-cms-without-losing-your-head-3ef9"&gt;good content management user interfaces&lt;/a&gt; are built into API-based headless CMS websites.&lt;/p&gt;

&lt;h4&gt;
  
  
  Few Git-based CMS options
&lt;/h4&gt;

&lt;p&gt;There are drag-and-drop content editors that play nicely with storing your content in the same Git repository as the site’s template codebase, like Netlify CMS and Forestry.io, but they’re not truly WYSIWYG experiences.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;TinaCMS is a Wix-like experience, but it doesn’t support Jekyll. From what I can tell, it leverages the front-end code that newer site generators like Gatsby and Next “hydrate” into the “DOM” to support its drag-and-drop functionality.&lt;/li&gt;
&lt;li&gt;The only Wix-like experience I’ve found so far that supports Jekyll is &lt;a href="https://app.stackbit.com/create?theme=https://github.com/kkgthb/web-site-jekyll-03-wysiwyg"&gt;Stackbit&lt;/a&gt; … but who knows if they will forever? I can’t imagine that adding a live-edit drag-and-drop skin to Jekyll’s &lt;code&gt;localhost&lt;/code&gt; engine has been easy for them to code, as amazing of a gift to the world it’s been that they figured it out.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>webdev</category>
      <category>jamstack</category>
      <category>jekyll</category>
    </item>
    <item>
      <title>Next.js Minimum Viable Build</title>
      <dc:creator>Katie</dc:creator>
      <pubDate>Mon, 23 Aug 2021 17:00:00 +0000</pubDate>
      <link>https://dev.to/katiekodes/nextjs-minimum-viable-build-1a62</link>
      <guid>https://dev.to/katiekodes/nextjs-minimum-viable-build-1a62</guid>
      <description>&lt;p&gt;Like with &lt;a href="https://dev.to/katiekodes/gatsby-for-novices-and-dabblers-19nn"&gt;Gatsby for novices and dabblers&lt;/a&gt;, I need to work my way through Next.js, because I find it intimidating.&lt;/p&gt;

&lt;h2&gt;
  
  
  Process
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Get a &lt;a href="https://www.netlify.com/"&gt;Netlify.com&lt;/a&gt; free account&lt;/li&gt;
&lt;li&gt;Set up a Netlify.com site, connected to a GitHub private &lt;a href="https://github.com/kkgthb/web-site-nextjs-01-min-viable-build"&gt;repository&lt;/a&gt;, that contains just 2 files: 

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;/src/pages/index.js&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;/package.json&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;TEST IT:&lt;/strong&gt; Make sure you can visit &lt;code&gt;https://yoursite.netlify.com/&lt;/code&gt; as expected, without “page not found” errors.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;To do: Profit&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Magic words
&lt;/h2&gt;

&lt;p&gt;Next.js has a “&lt;a href="https://dev.to/katiekodes/how-to-break-and-rebuild-the-jamstack-2g24"&gt;magic&lt;/a&gt; folder” path of &lt;code&gt;/pages/&lt;/code&gt;, or &lt;code&gt;/src/pages/&lt;/code&gt; &lt;em&gt;(&lt;a href="https://nextjs.org/docs/advanced-features/src-directory"&gt;documentation&lt;/a&gt;)&lt;/em&gt;. I’ve learned since I started all this that in the &lt;a href="https://dev.to/katiekodes/what-is-a-static-site-generator-350o"&gt;static site generator&lt;/a&gt; world, “ &lt;strong&gt;routing&lt;/strong&gt; ” tends to refer to the ways you can configure the SSG to turn data you’re feeding it into actual URLs. Most of them have some way of automatically doing “routing” based on the way you named data folders or files, or the way you named template folders or files. Some of them will pretty much eat every folder they can get their hands on and try to route it &lt;em&gt;(11ty)&lt;/em&gt;; &lt;a href="https://nextjs.org/docs/basic-features/pages"&gt;others like Next.js seem to favor limiting this behavior, by default, to folders with “magic names” like &lt;code&gt;/pages/&lt;/code&gt;&lt;/a&gt; – and then there are some more &lt;a href="https://nextjs.org/docs/routing/dynamic-routes"&gt;advanced syntaxes for doing fancier “routing.”&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Files
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;/src/pages/index.js&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Since Gatsby and Next.js both use React / JSX as a templating language, I simply reused my &lt;code&gt;/src/pages/index.js&lt;/code&gt; file from &lt;a href="https://dev.to/katiekodes/gatsby-minimum-viable-build-3n13"&gt;Gatsby minimum viable build&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;(“&lt;a href="https://nextjs.org/docs/routing/introduction"&gt;Any React component defined in pages/*.js or src/pages/*.js will automatically become a page.&lt;/a&gt;“)&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;Home&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Hello world!&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;code&gt;/package.json&lt;/code&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "name" : "netlify-nextjs-test-01",
  "version": "0.0.1",
  "private": true,
  "scripts": {
    "dev": "next dev",
    "develop": "next dev",
    "start": "next start",
    "build": "next build"
  },
  "dependencies": {
    "next": "latest",
    "react": "latest",
    "react-dom": "latest"
  }
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Output
&lt;/h2&gt;

&lt;p&gt;The resulting page has the following HTML:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;charset=&lt;/span&gt;&lt;span class="s"&gt;"utf-8"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"viewport"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"width=device-width"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"next-head-count"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"2"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;noscript&lt;/span&gt; &lt;span class="na"&gt;data-n-css=&lt;/span&gt;&lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/noscript&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;defer=&lt;/span&gt;&lt;span class="s"&gt;""&lt;/span&gt; &lt;span class="na"&gt;nomodule=&lt;/span&gt;&lt;span class="s"&gt;""&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"/_next/static/chunks/polyfills-a54b4f32bdc1ef890ddd.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"/_next/static/chunks/webpack-61f1b6d34e7ba415b8c1.js"&lt;/span&gt; &lt;span class="na"&gt;defer=&lt;/span&gt;&lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"/_next/static/chunks/framework-9e6ae5c73d4e43bf334d.js"&lt;/span&gt; &lt;span class="na"&gt;defer=&lt;/span&gt;&lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"/_next/static/chunks/main-b9780dc6f4fa7abb3771.js"&lt;/span&gt; &lt;span class="na"&gt;defer=&lt;/span&gt;&lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"/_next/static/chunks/pages/_app-76f68770679821db743d.js"&lt;/span&gt; &lt;span class="na"&gt;defer=&lt;/span&gt;&lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"/_next/static/chunks/pages/index-518723d5d0e877e1fb3f.js"&lt;/span&gt; &lt;span class="na"&gt;defer=&lt;/span&gt;&lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"/_next/static/7d3ar6btJVD3RfAMzzNO0/_buildManifest.js"&lt;/span&gt; &lt;span class="na"&gt;defer=&lt;/span&gt;&lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"/_next/static/7d3ar6btJVD3RfAMzzNO0/_ssgManifest.js"&lt;/span&gt; &lt;span class="na"&gt;defer=&lt;/span&gt;&lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"__next"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;div&amp;gt;&lt;/span&gt;Hello world!&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;" __NEXT_DATA__"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"application/json"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;props&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;pageProps&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;page&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;query&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;buildId&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;7d3ar6btJVD3RfAMzzNO0&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;runtimeConfig&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;nextExport&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;autoExport&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;isFallback&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;scriptLoader&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Like with Gatsby output, there’s a lot of JavaScript embedded in my page, but the &lt;code&gt;&amp;lt;div&amp;gt;Hello world!&amp;lt;/div&amp;gt;&lt;/code&gt; I expect to see exists deep in the middle.&lt;/p&gt;




&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--X-Ig0rYM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://katiekodes.com/images/booksmany.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--X-Ig0rYM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://katiekodes.com/images/booksmany.jpg" alt="" width="880" height="214"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Posts In This Series
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Part 1 - &lt;a href="https://dev.to/katiekodes/next-js-for-novices-and-dabblers-364e-temp-slug-961341"&gt;Next.js for novices and dabblers&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Part 2 - This Article &lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Helpful links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/kkgthb/web-site-nextjs-01-min-viable-build"&gt;This codebase on GitHub&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>jamstack</category>
      <category>webdev</category>
      <category>nextjs</category>
    </item>
    <item>
      <title>Open a Salesforce scratch org in a different browser with CumulusCI</title>
      <dc:creator>Katie</dc:creator>
      <pubDate>Sat, 10 Jul 2021 15:00:00 +0000</pubDate>
      <link>https://dev.to/katiekodes/open-a-salesforce-scratch-org-in-a-different-browser-with-cumulusci-o60</link>
      <guid>https://dev.to/katiekodes/open-a-salesforce-scratch-org-in-a-different-browser-with-cumulusci-o60</guid>
      <description>&lt;p&gt;Using Salesforce's CumulusCI to manage SFDX scratch orgs?  I am.  I was working from a machine where Firefox is the default web browser, and Firefox didn't play nicely with Lightning-mode editing of custom metadata types &lt;em&gt;(it wouldn't ever render the main part of the page where I edit types)&lt;/em&gt;.  Nor would Firefox let me switch to Classic mode &lt;em&gt;(it kept logging me out of the scratch org)&lt;/em&gt;.  This is how I managed to open the scratch org in Chrome.&lt;/p&gt;

&lt;p&gt;This was the command I had been using to open a scratch org called &lt;code&gt;dev&lt;/code&gt; from within a VSCode command prompt whose base folder was a codebase already configured to work with scratch orgs from a given real "hub" org:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;cci org browser &lt;span class="nt"&gt;--org&lt;/span&gt; dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Luckily, it came with &lt;code&gt;--help&lt;/code&gt; instructions at the command line that were useful:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt; cci org browser --help

Usage: cci org browser [OPTIONS] [ORGNAME]

  Opens a browser window and logs into the org using the stored OAuth
  credentials

Options:
  --org TEXT       Alternate way to specify the target org. By default, runs
                   against the current default org.

  -p, --path TEXT  Navigate to the specified page after logging in.
  -r, --url-only   Display the target URL, but don't open a browser.
  --help           Show this message and exit.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So next, I tried:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;cci org browser &lt;span class="nt"&gt;--org&lt;/span&gt; dev &lt;span class="nt"&gt;--url-only&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It displayed a URL that, sure enough, I could copy, paste into Chrome, and log into this scratch org with.&lt;/p&gt;

&lt;p&gt;Much better -- now I can see the body of &lt;code&gt;https://my-dev-scratch-org.lightning.force.com/lightning/setup/CustomMetadata/home&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Tip:  Ctrl+Click on the link makes VSCode give me an option to copy rather than open.  This saves me from having to carefully select the URL from beginning to end.&lt;/p&gt;

</description>
      <category>salesforce</category>
    </item>
    <item>
      <title>Adding Tailwind to a Jekyll site on Windows</title>
      <dc:creator>Katie</dc:creator>
      <pubDate>Tue, 06 Jul 2021 15:00:00 +0000</pubDate>
      <link>https://dev.to/katiekodes/adding-tailwind-to-a-jekyll-site-on-windows-5bg9</link>
      <guid>https://dev.to/katiekodes/adding-tailwind-to-a-jekyll-site-on-windows-5bg9</guid>
      <description>&lt;p&gt;I've been wanting to migrate one of my web sites from the Github Pages Jekyll to 11ty for a while so that I could use Tailwind CSS and facitate a redesign of the look and feel.&lt;/p&gt;

&lt;p&gt;In the end, I realized that migrating old &lt;code&gt;.md&lt;/code&gt; files w/o &lt;a href="https://kittygiraudel.com/2020/11/30/from-jekyll-to-11ty/#heading-anchors"&gt;breaking anchor links to subsections&lt;/a&gt; was going to be a regex nightmare, and I'd be better off figuring out how to add Tailwind to Jekyll.&lt;/p&gt;

&lt;h2&gt;
  
  
  Minimum viable build
&lt;/h2&gt;

&lt;p&gt;I put up &lt;a href="https://github.com/kkgthb/web-site-jekyll-02-tailwind-tiny"&gt;my working code at Github&lt;/a&gt;, and here's a &lt;a href="https://jekylltailwind.netlify.app/"&gt;live demo&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This is the first codebase I got working while implementing &lt;a href="https://stevenwestmoreland.com/2021/01/using-tailwind-css-with-jekyll.html"&gt;Steven Westmoreland's&lt;/a&gt; and &lt;a href="https://mdoliwa.com/articles/how-to-setup-jekyll-with-tailwind-css"&gt;Marcin Doliwa's&lt;/a&gt; directions to add Tailwind to &lt;a href="https://github.com/kkgthb/web-site-jekyll-01-tiny"&gt;this tiny Jekyll site&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I failed trying a million and a half more complex starters involving webpack, gulp, etc.  I'm glad the solution turned out simple in the end &lt;em&gt;(Ruby's &lt;code&gt;jekyll-postcss&lt;/code&gt; plugin)&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Clone it, run it, and play with the Tailwind classes in &lt;code&gt;pages/index.md&lt;/code&gt; yourself.&lt;/p&gt;

&lt;h2&gt;
  
  
  Issues
&lt;/h2&gt;

&lt;h3&gt;
  
  
  JIT
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;jekyll-postcss&lt;/code&gt; works just fine, as long as you don't expect Tailwind to work in JIT mode &lt;em&gt;(&lt;a href="https://github.com/mhanberg/jekyll-postcss/issues/22"&gt;bug report 1&lt;/a&gt;, &lt;a href="https://github.com/tailwindlabs/tailwindcss-jit/issues/41"&gt;bug report 2&lt;/a&gt;)&lt;/em&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  SCSS
&lt;/h3&gt;

&lt;p&gt;I also haven't gotten this architecture properly handling an &lt;code&gt;assets/css/main.scss&lt;/code&gt; &lt;em&gt;(note &lt;strong&gt;S&lt;/strong&gt;css)&lt;/em&gt; file; just plain CSS.&lt;/p&gt;

&lt;h3&gt;
  
  
  Windows
&lt;/h3&gt;

&lt;p&gt;If your localhost environment is on Windows, &lt;code&gt;jekyll-postcss&lt;/code&gt; will fail with an &lt;code&gt;ENOEXEC&lt;/code&gt; &lt;code&gt;Exec format error&lt;/code&gt; something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;...
Conversion error: Jekyll::Converters::PostCss encountered an error &lt;span class="k"&gt;while &lt;/span&gt;converting &lt;span class="s1"&gt;'assets/css/main.css'&lt;/span&gt;:
                    Exec format error - C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/jekyll-postcss-0.4.1/bin/postcss &lt;span class="s1"&gt;'{"raw_content":"@import \"tailwindcss/base\";\n@import \"tailwindcss/components\";\n@import \"tailwindcss/utilities\";"}'&lt;/span&gt;
...
C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/jekyll-postcss-0.4.1/lib/jekyll-postcss/socket.rb:20:in &lt;span class="sb"&gt;``&lt;/span&gt;&lt;span class="s1"&gt;': Exec format error - C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/jekyll-postcss-0.4.1/bin/postcss '&lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"raw_content"&lt;/span&gt;:&lt;span class="s2"&gt;"@import &lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;tailwindcss/base&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;";&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;n@import &lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;tailwindcss/components&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;";&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;n@import &lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;tailwindcss/utilities&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;";"&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;' (Errno::ENOEXEC)
...
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You have to install the Windows Subsystem for Linux &lt;em&gt;(WSL)&lt;/em&gt; as in &lt;a href="https://www.hanselman.com/blog/ruby-on-rails-on-windows-is-not-just-possible-its-fabulous-using-wsl2-and-vs-code"&gt;Scott Hanselman's instructions&lt;/a&gt; and run Jekyll from a &lt;strong&gt;WSL&lt;/strong&gt; command line.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;(Be sure to remember to run &lt;code&gt;bundle install&lt;/code&gt; and &lt;code&gt;npm i&lt;/code&gt; in WSL first to install the Ruby and Node.js codebases.)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Thanks to &lt;a href="https://veselin.dev/"&gt;Veselin Romic&lt;/a&gt; and &lt;a href="https://brittneypostma.com/"&gt;Brittney Postma&lt;/a&gt; for debugging &lt;a href="https://github.com/mhanberg/jekyll-postcss/issues/27#issuecomment-874362958"&gt;my stacktrace&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Github Pages
&lt;/h3&gt;

&lt;p&gt;Adding Tailwind to Jekyll requires moving the site off of GitHub Pages as a build engine, because GitHub Pages doesn't let you use more than a few preapproved Jekyll plugins, and &lt;code&gt;jekyll-postcss&lt;/code&gt; isn't one of them.&lt;/p&gt;

&lt;p&gt;This migration will involve writing a &lt;code&gt;Gemfile&lt;/code&gt; and letting a less restrictive build engine + CDN, like Netlify, build and host the site instead.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;(I mean, you could use a build engine and have it write output to GitHub and use GitHub Pages to host that output, but ... &lt;strong&gt;why&lt;/strong&gt;, now that services like Netlify exist?)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;GitHub provides a &lt;code&gt;github-pages&lt;/code&gt; plugin that can be added to a &lt;code&gt;Gemfile&lt;/code&gt; to facilitate building sites written for their environment to a different build engine &lt;em&gt;(it also helps w/ &lt;code&gt;localhost&lt;/code&gt; development, as )&lt;/em&gt;.  It looks like &lt;code&gt;github-pages-unscramble&lt;/code&gt; might be handy, too, when the time comes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Other notes
&lt;/h2&gt;

&lt;p&gt;For convenience, my sample web site includes some &lt;code&gt;package.json&lt;/code&gt; commands that let you type less text to kick off Jekyll.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Instead of running &lt;code&gt;NODE_ENV=production JEKYLL_ENV=production bundle exec jekyll build&lt;/code&gt; &lt;/li&gt;
&lt;li&gt;Instead of running &lt;code&gt;NODE_ENV=development JEKYLL_ENV=development bundle exec jekyll serve&lt;/code&gt; you can run &lt;code&gt;npm run develop&lt;/code&gt; or &lt;code&gt;npm run dev&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Background (why Tailwind)
&lt;/h2&gt;

&lt;p&gt;When I first encountered utility CSS class libraries like Tailwind, I &lt;em&gt;hated&lt;/em&gt; them.  Who on &lt;em&gt;earth&lt;/em&gt; would want to take easy-to-read HTML and turn it into such a nightmare?&lt;/p&gt;

&lt;p&gt;However, once I got used to it &lt;em&gt;(so that I could start playing with copy-paste pre-styled page section component libraries like Tailwind UI)&lt;/em&gt;, and once I got used to &lt;a href="https://www.stackbit.com/docs/knowledge-base/building-with-components"&gt;sectioning static site generator templates appropriately for page section components&lt;/a&gt;, suddenly the idea of styling components anywhere &lt;em&gt;but&lt;/em&gt; within the file that the HTML lived in seemed disorganized &amp;amp; annoying.&lt;/p&gt;

&lt;p&gt;As verbose as utility classes could be, at least they lived &amp;amp; died with their HTML, and that was comforting somehow.&lt;/p&gt;

&lt;p&gt;I could add or remove page elements at will and not worry about breaking things or leaving behind confusing artifacts.&lt;/p&gt;

&lt;p&gt;I've recently worked out how to add Algolia search to a Jekyll site, but the navigation bar on that site was a "don't touch code you don't understand" hot mess.  I've worked out a navbar I trust over the last few months in Tailwind, and into which I've successfully put a search widget.  I decided I'd be best off just rearchitecting the whole site's theme to be componentized &amp;amp; to use Tailwind CSS, so that it'd be easy not only to add search, but anything else that might come up in the future.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>jamstack</category>
      <category>tailwindcss</category>
      <category>jekyll</category>
    </item>
    <item>
      <title>Jamstack live preview tooling (a Next.js Conf reaction list)</title>
      <dc:creator>Katie</dc:creator>
      <pubDate>Tue, 15 Jun 2021 16:00:00 +0000</pubDate>
      <link>https://dev.to/katiekodes/jamstack-live-preview-tooling-2j9d</link>
      <guid>https://dev.to/katiekodes/jamstack-live-preview-tooling-2j9d</guid>
      <description>&lt;p&gt;Vercel announced &lt;a href="https://nextjs.org/live"&gt;Next.js Live&lt;/a&gt;, real-time previews with live collaborative editing at &lt;a href="https://nextjs.org/conf"&gt;Next.js conf&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This seemed like a good time to list all the options I’ve explored over the past year.&lt;/p&gt;

&lt;h2&gt;
  
  
  Next.js Live
&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://nextjs.org/live"&gt;landing page&lt;/a&gt; is hot pink, purple, and intense sky blue. Who cares about the product? Their landing page wins.&lt;/p&gt;

&lt;p&gt;Okay, for real, I’m guessing this is a VSCode-based &lt;code&gt;localhost&lt;/code&gt;-in-the-cloud product like I covered in “&lt;a href="https://dev.to/katiekodes/stackbit-can-teach-you-web-development-3blh"&gt;Stackbit can teach you web development&lt;/a&gt;,” and I’ll bet there are a lot more coming from a glut of companies. I wouldn’t be surprised if it’s &lt;strong&gt;standard within a year&lt;/strong&gt; for Jamstack tooling.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;(Way to date my post and make it possibly age like milk.)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The main value-add I’m seeing from the landing page is whatever front-end special sauce Vercel added to their preview renders for doodling on the preview.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--egkHE9WI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://nextjs.org/_next/image%3Furl%3D%252F_next%252Fstatic%252Fimage%252Fpublic%252Fstatic%252Flive%252Fbrowser.f5aa736f88c19b45aa423f7b1c0ca58f.png%26w%3D3840%26q%3D75" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--egkHE9WI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://nextjs.org/_next/image%3Furl%3D%252F_next%252Fstatic%252Fimage%252Fpublic%252Fstatic%252Flive%252Fbrowser.f5aa736f88c19b45aa423f7b1c0ca58f.png%26w%3D3840%26q%3D75" alt="Screenshot of Next.js live doodling"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Stackbit Studio
&lt;/h2&gt;

&lt;p&gt;In April, &lt;a href="https://www.stackbit.com/blog/vs-code-experience-to-stackbit-editor/"&gt;Stackbit added VSCode&lt;/a&gt; to a product whose bread and butter has always been a &lt;code&gt;localhost&lt;/code&gt;-in-the-cloud product.&lt;/p&gt;

&lt;p&gt;Stackbit’s value-add front-end special sauce, added to their preview renders, has, of course, always been the ability to type onto the page and edit content.&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/NU7zHKSX-nU"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;They also did a nifty thing w/ the VSCode editor where you can click parts of the preview render and &lt;a href="https://dev.to/katiekodes/stackbit-can-teach-you-web-development-3blh"&gt;jump to&lt;/a&gt; the line of &lt;a href="https://dev.to/katiekodes/what-is-a-static-site-generator-350o"&gt;SSG&lt;/a&gt; code most directly responsible for it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Gatsby Cloud Preview
&lt;/h2&gt;

&lt;p&gt;It’s been a while since I looked into Gatsby Cloud. They’ve changed their plans since I blogged about their preview-URLs-without-a-full-branch-rebuild feature, but when I did, one problem was that &lt;a href="https://katiekodes.com/gatsby-sanity-deploy/#preview-urls-disappear"&gt;the links weren’t stable&lt;/a&gt;, and that you didn’t really have another business reason to be in the tooling where you’d grab a fresh link the way you would in, say, a VSCode-editor interface like Next.js Live or Stackbit. I’d be really surprised if Gatsby &lt;em&gt;didn’t&lt;/em&gt; throw a VSCode embed into some sort of tool just to keep up with the Joneses against Next.js.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--2BwyRv7v--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://katiekodes.com/images/screenshots/screenshot-gatsby-sanity-2020-07/65-live-editing-animated.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--2BwyRv7v--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://katiekodes.com/images/screenshots/screenshot-gatsby-sanity-2020-07/65-live-editing-animated.gif" alt="Screencap of Gatsby Preview next to Sanity Studio"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Netlify Deploy Previews
&lt;/h2&gt;

&lt;p&gt;I haven’t played w/ &lt;a href="https://www.netlify.com/products/deploy-previews/"&gt;Deploy Previews&lt;/a&gt; … does anyone know if they’re live &lt;em&gt;(as in &lt;code&gt;localhost&lt;/code&gt;-in-the-cloud, not “I’ll rebuild a preview site when you commit an update to a feature branch”)&lt;/em&gt; previews? Or if they’re just a comment-doodling system laid on top of feature-branch built sites?&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>jamstack</category>
      <category>nextjs</category>
    </item>
  </channel>
</rss>
