<?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: Loftie Ellis</title>
    <description>The latest articles on DEV Community by Loftie Ellis (@lpellis).</description>
    <link>https://dev.to/lpellis</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%2F139093%2Fac92849a-17ed-4273-a088-5ee97bfc6590.jpg</url>
      <title>DEV Community: Loftie Ellis</title>
      <link>https://dev.to/lpellis</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/lpellis"/>
    <language>en</language>
    <item>
      <title>Can you save on LLM tokens using images instead of text?</title>
      <dc:creator>Loftie Ellis</dc:creator>
      <pubDate>Sat, 01 Nov 2025 20:19:16 +0000</pubDate>
      <link>https://dev.to/lpellis/can-you-save-on-llm-tokens-using-images-instead-of-text-1338</link>
      <guid>https://dev.to/lpellis/can-you-save-on-llm-tokens-using-images-instead-of-text-1338</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;TLDR: Yes, but only under specific conditions, and it is probably not worth the trade-offs.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The &lt;a href="https://arxiv.org/abs/2510.18234" rel="noopener noreferrer"&gt;recent OCR paper from DeepSeek&lt;/a&gt; and the &lt;a href="https://news.ycombinator.com/item?id=45658928" rel="noopener noreferrer"&gt;related discussion&lt;/a&gt; reminded me of something curious I noticed with the OpenAI API - Prompts that use images as input consume almost the same number of tokens as those that use text, even though the images could be 50x the size of the text.&lt;/p&gt;

&lt;p&gt;This made me think, could you actually save on tokens by converting your text to an image and sending that to the api?&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting up an experiment
&lt;/h2&gt;

&lt;p&gt;To test the theory, I ran a simple prompt using both text only and an image-based one.&lt;/p&gt;

&lt;p&gt;For the prompt I'm asking ChatGPT to pick out and summarize the information from &lt;a href="https://karpathy.bearblog.dev/digital-hygiene/" rel="noopener noreferrer"&gt;this post by Karpathy on digital hygiene&lt;/a&gt;. It should be something LLMs are good at, but there is also a clear correct answer so it's easy to check.&lt;/p&gt;

&lt;p&gt;The prompt is simply the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;List every hygiene tip from the collection, with a short sentence summary.
List the titles * EXACTLY * as in the text
Follow the following format:
** Title 1 ** - summary 1
** Title 2 ** - summary 2
DO NOT ask any followup questions, simply return the list.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To run the prompt I extracted the &lt;a href="https://gist.github.com/lpellis/8f00d5d7554fcd4cc7572f6ddb7d6912" rel="noopener noreferrer"&gt;text-only version of the blogpost&lt;/a&gt; (skipping the headers and image), and fed it to gpt-5&lt;/p&gt;

&lt;p&gt;The output is as expected:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;**Password manager** - Use a password manager to store and generate unique passwords to prevent reuse and leaks across services.
**Hardware security key** - Strengthen your accounts with physical security keys like YubiKeys for superior protection against attacks and SIM swaps.
**Biometrics** - Use biometric authentication, such as FaceID, as an additional factor of security where available.
**Security questions** - Avoid traditional security questions; use random passwords instead to prevent easy guessing or phishing.
.. etc

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

&lt;/div&gt;



&lt;p&gt;The next step is to run the prompt on the image instead of text.&lt;/p&gt;

&lt;h3&gt;
  
  
  Converting the prompt to an image
&lt;/h3&gt;

&lt;p&gt;When creating the image we need to be careful to get the dimensions right, otherwise OpenAI will resize the image and won't be able to make out any text.&lt;/p&gt;

&lt;p&gt;Looking through their &lt;a href="https://platform.openai.com/docs/guides/images-vision?api-mode=responses" rel="noopener noreferrer"&gt;documentation&lt;/a&gt;, the ideal size seems to be 768x768, so I wrote a &lt;a href="https://gist.github.com/lpellis/f7064bee73ce4a3c22aebea819f2665a" rel="noopener noreferrer"&gt;basic puppeteer script&lt;/a&gt; to convert the post to an image with these dimensions.&lt;/p&gt;

&lt;p&gt;To fit into the desired resolution, I had to break the prompt into two images; you can see them &lt;a href="///blog/images/screenshot_full_1.png"&gt;here&lt;/a&gt; and &lt;a href="///blog/images/screenshot_full_2.png"&gt;here&lt;/a&gt;.&lt;br&gt;
When running the prompt, you have to specify both images with "detail": "high"&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    model='gpt-5',
    messages=[{
        'role': 'user',
        'content': [
            {"type": "image_url",  "image_url": {"url": f"{im_1}", "detail": "high"}},
            {"type": "image_url",  "image_url": {"url": f"{im_2}", "detail": "high"}},
        ],
    },
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This worked perfectly, and the output was similar to using the text-based prompts (though it did take almost twice as long to process).&lt;/p&gt;

&lt;h2&gt;
  
  
  The Results
&lt;/h2&gt;

&lt;p&gt;Running the prompt with a few different models, we can see there are indeed significant savings in prompt tokens.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxmtsk8ytc2bz5bapcf22.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxmtsk8ytc2bz5bapcf22.png" alt="Prompt Tokens" width="763" height="347"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;With gpt-5 in particular, we get over a 40% reduction in prompt tokens.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Completion Tokens
&lt;/h3&gt;

&lt;p&gt;Prompt tokens are only half the story, though.&lt;/p&gt;

&lt;p&gt;Running the prompt five times with each model and taking the average, we see the following:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvu45d51408tfelv2x96h.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvu45d51408tfelv2x96h.png" alt="Completion Tokens" width="763" height="345"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;All models apart from gpt-5-chat use significantly more completion tokens with the image inputs&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Completion tokens are also significantly more expensive, so unless you use the chat model, you are not getting any savings.&lt;/p&gt;

</description>
      <category>llm</category>
      <category>ai</category>
      <category>openai</category>
    </item>
    <item>
      <title>Finding the largest favicon with js</title>
      <dc:creator>Loftie Ellis</dc:creator>
      <pubDate>Thu, 26 Nov 2020 23:27:16 +0000</pubDate>
      <link>https://dev.to/lpellis/finding-the-largest-favicon-with-js-3an8</link>
      <guid>https://dev.to/lpellis/finding-the-largest-favicon-with-js-3an8</guid>
      <description>&lt;p&gt;As part of an audit I wanted to fetch the highest quality favicon for every page that we check. It turned out to be slightly more complicated than I thought:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://stackoverflow.com/questions/2057636/get-websites-favicon-with-js" rel="noopener noreferrer"&gt;These&lt;/a&gt; &lt;a href="https://stackoverflow.com/questions/1990475/how-can-i-retrieve-the-favicon-of-a-website" rel="noopener noreferrer"&gt;stackoverflow&lt;/a&gt; &lt;a href="https://stackoverflow.com/questions/10282939/how-to-get-favicons-url-from-a-generic-webpage-in-javascript" rel="noopener noreferrer"&gt;posts&lt;/a&gt; suggest a few ways to get the favicon, but they all share a few issues:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;It depends on a 3rd party (eg &lt;a href="https://www.google.com/s2/favicons?domain=www.bbc.co.uk" rel="noopener noreferrer"&gt;Google&lt;/a&gt;)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It ignores the default &lt;code&gt;/favicon.ico&lt;/code&gt;, or uses it incorrectly&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It returns the first favicon, instead of the largest one&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  How the browser chooses a favicon
&lt;/h3&gt;

&lt;p&gt;The standard way to include a favicon is with a link tag &lt;code&gt;&amp;lt;link rel="icon"..&lt;/code&gt; You can use multiple link tags to specify different sizes, for example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;link rel="icon" sizes="16x16" href="/favicon_16.png"&amp;gt;
&amp;lt;link rel="icon" sizes="32x32" href="/favicon_32.png"&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Another popular variant is &lt;code&gt;&amp;lt;link rel="shortcut icon"..&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;link rel="shortcut icon" href="/favicon_32.png"&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If none of these tags are present the browser will make a request to the &lt;code&gt;/favicon.ico&lt;/code&gt; file at the root directory. Some servers are badly configured though and will return an &lt;code&gt;200 OK&lt;/code&gt; status even if the file is not present, so to be sure you have to check that the file is indeed an image.&lt;/p&gt;

&lt;h3&gt;
  
  
  The solution
&lt;/h3&gt;

&lt;p&gt;The following codes combines all these factors, and loops through the available favicons to return the largest one.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Get the largest favicon in the current document, or false if none is found.
let getLargestFavicon = async () =&amp;gt; {
  let getSize = el =&amp;gt; {
    return (el.sizes[0] &amp;amp;&amp;amp; parseInt(el.sizes[0], 10)) || 0;
  };
  let favicons = [
    ...document.querySelectorAll('link[rel="shortcut icon"],link[rel="icon"]')
  ].sort((a, b) =&amp;gt; {
    return getSize(b) - getSize(a);
  });
  if (favicons.length &amp;gt; 0) {
    return favicons[0].href;
  }
  // no favicon is specified in the meta tags, lets try the default /favicon.ico
  let defaultLocation = document.location.origin + "/favicon.ico";
  let r = await fetch(defaultLocation);
  if (r.ok) {
    let t = await r.blob();
    if (t.type.indexOf("image") !== -1) {
      return defaultLocation;
    }
  }
  return false;
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Originally published at &lt;a href="https://blog.pagewatch.dev/post/finding-the-largest-favicon-with-js" rel="noopener noreferrer"&gt;https://blog.pagewatch.dev/post/finding-the-largest-favicon-with-js&lt;/a&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Switching from Netlify to SimpleAnalytics</title>
      <dc:creator>Loftie Ellis</dc:creator>
      <pubDate>Thu, 30 Jul 2020 21:17:12 +0000</pubDate>
      <link>https://dev.to/lpellis/switching-from-netlify-to-simpleanalytics-e3</link>
      <guid>https://dev.to/lpellis/switching-from-netlify-to-simpleanalytics-e3</guid>
      <description>&lt;p&gt;I moved my web analytics for &lt;a href="https://pagewatch.dev/" rel="noopener noreferrer"&gt;PageWatch&lt;/a&gt;, my blog and some personal projects to &lt;a href="https://simpleanalytics.com/" rel="noopener noreferrer"&gt;Simple Analytics&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I wanted a simple, privacy focused analytics platform (no cookie banners!), and initially tried Netlify Analytics (since most of my sites are hosted there)&lt;/p&gt;

&lt;p&gt;For starters it worked out well: There is no setup required, and Netlify will even backfill old data for you (data they collected from their server logs before you enabled analytics).&lt;/p&gt;

&lt;h3&gt;
  
  
  I quickly ran into a few issues:
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy1fg6b6ga3p4n2owqkjc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy1fg6b6ga3p4n2owqkjc.png" width="261" height="360"&gt;&lt;/a&gt;&lt;/p&gt;
Netlify Analytics is functional but a bit limited



&lt;p&gt;&lt;strong&gt;Cost&lt;/strong&gt;: Netlify analytics is $9/month, per site. That is cheap if you have just a few sites, but I have quite a few, and most hardly generate any traffic. SimpleAnalytics on the other hand is $19/month for unlimited sites.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Limited Data&lt;/strong&gt;: Netlify only shows me the top 5 referral sources, in contrast to SimpleAnalytics where I can drill down much more, as well as see Twitter posts and other social data.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg736y5xwk3abtig9t0hj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg736y5xwk3abtig9t0hj.png" width="500" height="305"&gt;&lt;/a&gt;&lt;/p&gt;
Netlify reports nearly all traffic going to /



&lt;p&gt;&lt;strong&gt;No SPA support&lt;/strong&gt;: This is kind of ironic seeing that Netlify is often used to host SPA's. For PageWatch, Netlify reported nearly all the traffic as going to the top level page, which isn't even a valid destination.&lt;/p&gt;

&lt;h3&gt;
  
  
  Switching to SimpleAnalytics
&lt;/h3&gt;

&lt;p&gt;SimpleAnalytics promises to be simple, privacy focused with all the essentials, and so far it has delivered.&lt;/p&gt;

&lt;p&gt;Installing is simple, you just have to add a single line of code to your site.&lt;/p&gt;

&lt;p&gt;This blog is built on Gridsome, and there was even plugin available:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ npm install gridsome-plugin-simple-analytics
# then simply add the following settings
module.exports = {
  plugins: [
    {
      use: 'gridsome-plugin-simple-analytics'
    }
  ]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Made by another IndieHacker
&lt;/h3&gt;

&lt;p&gt;SimpleAnalytics is &lt;a href="https://www.indiehackers.com/product/simple-analytics" rel="noopener noreferrer"&gt;a small but growing project&lt;/a&gt;, and I like to support other makers whenever I can.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsg006cdv35kqz5r5gvzv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsg006cdv35kqz5r5gvzv.png" width="534" height="492"&gt;&lt;/a&gt;&lt;/p&gt;
PageWatch Dashboard. Hopefully one day the graph will look more impressive



&lt;p&gt;Originally published at &lt;a href="https://blog.pagewatch.dev/post/switching-from-netlify-to-simpleanalytics" rel="noopener noreferrer"&gt;https://blog.pagewatch.dev/post/switching-from-netlify-to-simpleanalytics&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
    </item>
    <item>
      <title>What are those LSEP characters on certain pages?</title>
      <dc:creator>Loftie Ellis</dc:creator>
      <pubDate>Sat, 13 Jun 2020 01:11:15 +0000</pubDate>
      <link>https://dev.to/lpellis/what-are-those-lsep-characters-on-certain-pages-13b8</link>
      <guid>https://dev.to/lpellis/what-are-those-lsep-characters-on-certain-pages-13b8</guid>
      <description>&lt;p&gt;If you browse the web on windows, you might have from time to time see characters like these:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvzt28fvq7rx1m27v9cpq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvzt28fvq7rx1m27v9cpq.png" width="176" height="168"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;That character is actually the Unicode U+2028 Line Separator, and for some reason Chrome will display it as a visible block.&lt;/p&gt;

&lt;h3&gt;
  
  
  How did it get there?
&lt;/h3&gt;

&lt;p&gt;Most likely the developer has an IDE that accidentally placed those characters in place of a new line, or there is some server side script that incorrectly processed newlines. Either way it is very likely that these go unspotted as they do not show at all on most operating systems or browsers.&lt;/p&gt;

&lt;p&gt;See &lt;a href="https://stackoverflow.com/questions/39603446/why-is-this-symbol-showing-up-on-chrome-and-not-firefox-or-edge?noredirect=1&amp;amp;lq=1" rel="noopener noreferrer"&gt;this stackoverflow post&lt;/a&gt; for more context.&lt;/p&gt;

&lt;h3&gt;
  
  
  How to fix?
&lt;/h3&gt;

&lt;p&gt;If this was due to and IDE, you can simply search and replace the code. Go &lt;a href="https://www.fileformat.info/info/unicode/char/2028/browsertest.htm" rel="noopener noreferrer"&gt;here&lt;/a&gt; and copy the text (it might look like just an empty character), and replace those with a blank space.&lt;/p&gt;

&lt;p&gt;If the characters ended up in the database you might be able to run a sql query (see the stackoverflow post above) to get rid of them.&lt;/p&gt;

&lt;p&gt;Either way it is a good idea to preview your pages in Chrome on windows, or use &lt;a href="https://pagewatch.dev" rel="noopener noreferrer"&gt;PageWatch&lt;/a&gt; to automatically find these in your site.&lt;/p&gt;

&lt;p&gt;Originally published at &lt;a href="https://blog.pagewatch.dev/post/what-are-those-lsep-characters-on-certain-pages" rel="noopener noreferrer"&gt;https://blog.pagewatch.dev/post/what-are-those-lsep-characters-on-certain-pages&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
    </item>
    <item>
      <title>IndieHackers light theme</title>
      <dc:creator>Loftie Ellis</dc:creator>
      <pubDate>Wed, 10 Jun 2020 21:54:27 +0000</pubDate>
      <link>https://dev.to/lpellis/indiehackers-light-theme-1ki</link>
      <guid>https://dev.to/lpellis/indiehackers-light-theme-1ki</guid>
      <description>&lt;p&gt;I built a light theme extension (Chrome for now) for &lt;a href="https://www.indiehackers.com/" rel="noopener noreferrer"&gt;indiehackers&lt;/a&gt;, for the few people like me who prefer a light background :)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh00j0a2zu4vhe74c317f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh00j0a2zu4vhe74c317f.png" width="625" height="500"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;I really enjoy reading people's stories over there, and actually find the current look quite pleasing. My problem though is I prefer to code with a light background in my IDE, and if spend enough time on this site my eyes adjust, and then switching back its like staring into the sun.&lt;/p&gt;

&lt;p&gt;This extension adds a very basic light theme, and you can quickly toggle back for a session by clicking the extension icon. (it will toggle back to dark for the current tab)&lt;/p&gt;

&lt;p&gt;Hope someone finds it useful: The code is open source (MIT) and available from &lt;a href="https://github.com/lpellis/IndieHackers-Light-Theme" rel="noopener noreferrer"&gt;https://github.com/lpellis/IndieHackers-Light-Theme&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Originally published at &lt;a href="https://loftie.com/post/indiehackers-light-theme" rel="noopener noreferrer"&gt;https://loftie.com/post/indiehackers-light-theme&lt;/a&gt;&lt;/p&gt;

</description>
      <category>showdev</category>
    </item>
    <item>
      <title>Python Tip: Auto-reload the console on file changes</title>
      <dc:creator>Loftie Ellis</dc:creator>
      <pubDate>Sat, 21 Dec 2019 20:00:33 +0000</pubDate>
      <link>https://dev.to/lpellis/python-tip-auto-reload-the-console-on-file-changes-ph0</link>
      <guid>https://dev.to/lpellis/python-tip-auto-reload-the-console-on-file-changes-ph0</guid>
      <description>&lt;p&gt;I find myself using the python console often in python (and Django) to test various things. But one annoying thing was that I had to restart the console (and all imports/commands until the line) every time I made the change.&lt;/p&gt;

&lt;p&gt;There is a better way though.&lt;/p&gt;

&lt;h3&gt;
  
  
  IPython autoreload
&lt;/h3&gt;

&lt;p&gt;If you use IPython as your console, you can use the &lt;code&gt;autoreload&lt;/code&gt; extension to automatically reload code up the current state. This makes the following flow possible:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;In [1]: %load_ext autoreload

In [2]: %autoreload 2

In [3]: from foo import some_function

In [4]: some_function()
Out[4]: 42

In [5]: # open foo.py in an editor and change some_function to return 43

In [6]: some_function()
Out[6]: 43
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;See &lt;a href="https://ipython.readthedocs.io/en/stable/config/extensions/autoreload.html" rel="noopener noreferrer"&gt;https://ipython.readthedocs.io/en/stable/config/extensions/autoreload.html&lt;/a&gt; for more information.&lt;/p&gt;

&lt;h3&gt;
  
  
  Usage in PyCharm
&lt;/h3&gt;

&lt;p&gt;PyCharm &lt;a href="https://youtrack.jetbrains.com/issue/PY-14631?_ga=2.165123775.1472087216.1576953980-274049246.1575574552" rel="noopener noreferrer"&gt;does not yet fully support the IPython config&lt;/a&gt;, but you can still set it up without too much work.&lt;/p&gt;

&lt;p&gt;First, make sure you have IPython installed:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;pip install ipython&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;*Then, in &lt;code&gt;Settings-&amp;gt;Build,Execution,Deployment-&amp;gt;Console&lt;/code&gt; make sure you have 'Use IPython if available' checked.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Last step is to add the following two lines to the Starting script.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;%load_ext autoreload
%autoreload 2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8fxj2o2gxhysyowlxtzj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8fxj2o2gxhysyowlxtzj.png" width="660" height="224"&gt;&lt;/a&gt;&lt;/p&gt;
Console settings in PyCharm



&lt;p&gt;That's it, now your console will automatically reload whenever you make file changes.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Also check out my other article for how to &lt;a href="https://loftie.com/post/django-console-tip/" rel="noopener noreferrer"&gt;automatically load your models in the Django console.&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>python</category>
      <category>django</category>
    </item>
    <item>
      <title>PyDevTo - unofficial dev.to api for python</title>
      <dc:creator>Loftie Ellis</dc:creator>
      <pubDate>Sun, 03 Nov 2019 22:34:07 +0000</pubDate>
      <link>https://dev.to/lpellis/pydevto-unofficial-dev-to-api-for-python-pbj</link>
      <guid>https://dev.to/lpellis/pydevto-unofficial-dev-to-api-for-python-pbj</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Dev.to has a pretty awesome community for sharing coding knowledge. I wanted to republish my posts to them (and also link to the comments) so I made this library, and in the interest of sharing decided to opensource it for anyone to use.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://github.com/lpellis/pydevto" rel="noopener noreferrer"&gt;PyDevTo&lt;/a&gt; is a a wrapper around the &lt;a href="https://docs.dev.to/api/"&gt;dev.to api endoints&lt;/a&gt;, with a few helper functions to help with the distribution of articles.&lt;/p&gt;

&lt;h3&gt;
  
  
  Features
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Implements all endpoints from &lt;a href="https://docs.dev.to/api/"&gt;https://docs.dev.to/api/&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Implements a few other api endpoints not documented but available in the source, such as users and follow_suggestions.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Includes a helper method to convert html to dev.to specific markdown, including support for dev.to specific embeds such as YouTube.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Installation
&lt;/h2&gt;

&lt;p&gt;Use the package manager &lt;a href="https://pip.pypa.io/en/stable/" rel="noopener noreferrer"&gt;pip&lt;/a&gt; to install pydevto.&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;pip install pydevto&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Usage
&lt;/h2&gt;

&lt;p&gt;Make sure you have an api key to use the authenticated endpoints. You can get your key from &lt;a href="https://dev.to/settings/account"&gt;https://dev.to/settings/account&lt;/a&gt; (You can use pydevto without an api key for some functions, such as the public articles)&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="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;pydevto&lt;/span&gt;
&lt;span class="n"&gt;api&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pydevto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;PyDevTo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;api_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;MY_KEY&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;api&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;articles&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;  &lt;span class="c1"&gt;# returns list of your own published articles
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Methods
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;pydevto&lt;/span&gt;
&lt;span class="n"&gt;api&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pydevto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;PyDevTo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;api_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;MY_KEY&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;api&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;public_articles&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tag&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;top&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# Return list of public (published) articles
&lt;/span&gt;&lt;span class="n"&gt;api&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;public_article&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# Return a single public (published) article given its id
&lt;/span&gt;&lt;span class="n"&gt;api&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;articles&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;per_page&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;published&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# Return a list of user articles
&lt;/span&gt;&lt;span class="n"&gt;api&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create_article&lt;/span&gt;&lt;span class="p"&gt;(...)&lt;/span&gt;  &lt;span class="c1"&gt;# Create an article
&lt;/span&gt;&lt;span class="n"&gt;api&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update_article&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...)&lt;/span&gt;  &lt;span class="c1"&gt;# Update an article
&lt;/span&gt;&lt;span class="n"&gt;api&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;user&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# Return user information
&lt;/span&gt;&lt;span class="n"&gt;api&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;follow_suggestions&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# Return list of follow suggestions
&lt;/span&gt;&lt;span class="n"&gt;api&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;tags&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# Return list of tags
&lt;/span&gt;&lt;span class="n"&gt;api&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;webhooks&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;  &lt;span class="c1"&gt;# Return list of webhooks
&lt;/span&gt;&lt;span class="n"&gt;api&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;webhook&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# Return single webhook with id
&lt;/span&gt;&lt;span class="n"&gt;api&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create_webhook&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;source&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;target_url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;events&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# Create a new webhook
&lt;/span&gt;&lt;span class="n"&gt;api&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;delete_webhook&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# Delete  a webhook with id
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;PyDevTo contains a helper function to convert html to dev.to specific markdown. (&lt;a href="https://dev.to/p/editor_guide"&gt;https://dev.to/p/editor_guide&lt;/a&gt;) It supports images with captions using the HTML figcaption tag, and converts embeds such as YouTube to dev.to specific liquid tags.&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="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;pydevto&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;pydevto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;html_to_markdown&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;&amp;lt;h1&amp;gt;Heading&amp;lt;/h1&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;# Heading&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;pydevto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;html_to_markdown&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;&amp;lt;iframe src=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://www.youtube.com/embed/kmjiUVEMvI4&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;&amp;gt;&amp;lt;/iframe&amp;gt;&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;{% youtube kmjiUVEMvI4 %}&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.dev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/lpellis" rel="noopener noreferrer"&gt;
        lpellis
      &lt;/a&gt; / &lt;a href="https://github.com/lpellis/pydevto" rel="noopener noreferrer"&gt;
        pydevto
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Unofficial dev.to api 
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;PyDevTo&lt;/h1&gt;
&lt;/div&gt;

&lt;p&gt;Unofficial dev.to api for python.&lt;/p&gt;

&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Features&lt;/h3&gt;
&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;Implements all endpoints from &lt;a href="https://docs.dev.to/api/" rel="nofollow"&gt;https://docs.dev.to/api/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Implements a few other api endpoints not documented but available in the source, such as users and follow_suggestions&lt;/li&gt;
&lt;li&gt;Includes a helper method to convert html to dev.to specific markdown, including support for dev.to specific embeds such as YouTube.&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Installation&lt;/h2&gt;
&lt;/div&gt;

&lt;p&gt;Use the package manager &lt;a href="https://pip.pypa.io/en/stable/" rel="nofollow noopener noreferrer"&gt;pip&lt;/a&gt; to install pydevto.&lt;/p&gt;

&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;pip install pydevto&lt;/pre&gt;

&lt;/div&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Usage&lt;/h2&gt;

&lt;/div&gt;

&lt;p&gt;Make sure you have an api key to use the authenticated endpoints.  You can get your key from &lt;a href="https://dev.to/settings/account" rel="nofollow"&gt;https://dev.to/settings/account&lt;/a&gt;
(You can use pydevto without an api key for some functions, such as the public articles)&lt;/p&gt;

&lt;div class="highlight highlight-source-python notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;&lt;span class="pl-k"&gt;import&lt;/span&gt; &lt;span class="pl-s1"&gt;pydevto&lt;/span&gt;
&lt;span class="pl-s1"&gt;api&lt;/span&gt; &lt;span class="pl-c1"&gt;=&lt;/span&gt; &lt;span class="pl-s1"&gt;pydevto&lt;/span&gt;.&lt;span class="pl-c1"&gt;PyDevTo&lt;/span&gt;(&lt;span class="pl-s1"&gt;api_key&lt;/span&gt;&lt;span class="pl-c1"&gt;=&lt;/span&gt;&lt;span class="pl-s"&gt;'MY_KEY'&lt;/span&gt;)
&lt;span class="pl-s1"&gt;api&lt;/span&gt;.&lt;span class="pl-c1"&gt;articles&lt;/span&gt;()  &lt;span class="pl-c"&gt;# returns list of your own published articles&lt;/span&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Methods&lt;/h2&gt;

&lt;/div&gt;

&lt;div class="highlight highlight-source-python notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;&lt;span class="pl-k"&gt;import&lt;/span&gt; &lt;span class="pl-s1"&gt;pydevto&lt;/span&gt;
&lt;span class="pl-s1"&gt;api&lt;/span&gt; &lt;span class="pl-c1"&gt;=&lt;/span&gt; &lt;span class="pl-s1"&gt;pydevto&lt;/span&gt;.&lt;span class="pl-c1"&gt;PyDevTo&lt;/span&gt;(&lt;span class="pl-s1"&gt;api_key&lt;/span&gt;&lt;span class="pl-c1"&gt;=&lt;/span&gt;&lt;span class="pl-s"&gt;'MY_KEY'&lt;/span&gt;)
&lt;span class="pl-s1"&gt;api&lt;/span&gt;.&lt;span class="pl-c1"&gt;public_articles&lt;/span&gt;(&lt;span class="pl-s1"&gt;page&lt;/span&gt;&lt;span class="pl-c1"&gt;=&lt;/span&gt;&lt;span class="pl-c1"&gt;None&lt;/span&gt;, &lt;span class="pl-s1"&gt;tag&lt;/span&gt;&lt;span class="pl-c1"&gt;=&lt;/span&gt;&lt;span class="pl-c1"&gt;None&lt;/span&gt;, &lt;span class="pl-s1"&gt;username&lt;/span&gt;&lt;span class="pl-c1"&gt;=&lt;/span&gt;&lt;span class="pl-c1"&gt;None&lt;/span&gt;&lt;/pre&gt;…
&lt;/div&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/lpellis/pydevto" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;&lt;br&gt;&lt;br&gt;
Let me know if you run into any issues.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;PS I originally published this post at &lt;a href="https://loftie.com/post/pydevto-unofficial-devto-api" rel="noopener noreferrer"&gt;https://loftie.com/post/pydevto-unofficial-devto-api&lt;/a&gt; and used this very library to make this post :)&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>python</category>
      <category>showdev</category>
    </item>
    <item>
      <title>Things you may not know about Chrome DevTools</title>
      <dc:creator>Loftie Ellis</dc:creator>
      <pubDate>Wed, 25 Sep 2019 00:30:44 +0000</pubDate>
      <link>https://dev.to/lpellis/things-you-may-not-know-about-chrome-devtools-53k6</link>
      <guid>https://dev.to/lpellis/things-you-may-not-know-about-chrome-devtools-53k6</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;I use the Chrome Developer tools pretty much daily, but there are a few things I wish I knew earlier&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  1: Easily get a reference to any inspected element
&lt;/h3&gt;

&lt;p&gt;You can get a reference to any inspected element from the console by right-clicking on the element in the 'elements' view, and choosing 'Store as global variable'.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fximg%2Fimage%2Fupload%2Fw_732%2Ch_500%2Cc_limit%2Ff_auto%2Fwhoami%2F4a595384%2Fpost%2FgC1LZfdWhls6jTwa.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fximg%2Fimage%2Fupload%2Fw_732%2Ch_500%2Cc_limit%2Ff_auto%2Fwhoami%2F4a595384%2Fpost%2FgC1LZfdWhls6jTwa.png" width="732" height="434"&gt;&lt;/a&gt;Easily get a reference to any inspected element&lt;/p&gt;

&lt;h3&gt;
  
  
  2: Create live expressions pinned to your console
&lt;/h3&gt;

&lt;p&gt;You can create a live expression that is constantly evaluated and pinned to the top of your console. This can be very useful to watch certain elements that you know should update on the page.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fximg%2Fimage%2Fupload%2Fw_732%2Ch_500%2Cc_limit%2Ff_auto%2Fwhoami%2F4a595384%2Fpost%2FCerDLLPnIBzH1ftn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fximg%2Fimage%2Fupload%2Fw_732%2Ch_500%2Cc_limit%2Ff_auto%2Fwhoami%2F4a595384%2Fpost%2FCerDLLPnIBzH1ftn.png" width="562" height="136"&gt;&lt;/a&gt;Live expression in Chrome&lt;/p&gt;

&lt;h3&gt;
  
  
  3: Simulate slow internet
&lt;/h3&gt;

&lt;p&gt;You can simulate different internet speeds directly from the Network tab. Really useful to see how your code reacts when it can take several seconds to load.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fximg%2Fimage%2Fupload%2Fw_732%2Ch_500%2Cc_limit%2Ff_auto%2Fwhoami%2F4a595384%2Fpost%2FVqBC1UUS9Scg8n1T.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fximg%2Fimage%2Fupload%2Fw_732%2Ch_500%2Cc_limit%2Ff_auto%2Fwhoami%2F4a595384%2Fpost%2FVqBC1UUS9Scg8n1T.png" width="732" height="160"&gt;&lt;/a&gt;Test different internet speeds&lt;/p&gt;

&lt;h3&gt;
  
  
  4: Disable Caching, and preserve logs
&lt;/h3&gt;

&lt;p&gt;I have had many issues that turned out to be not errors at all, simply cached code that was wrongly loaded. To prevent this you can turn off all caching from the network tab. (Note that it will only disable cache when the DevTools window is open)&lt;/p&gt;

&lt;p&gt;Preserve logs are another useful feature to keeps your logs/console output from clearing when you navigate through different pages.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fximg%2Fimage%2Fupload%2Fw_732%2Ch_500%2Cc_limit%2Ff_auto%2Fwhoami%2F4a595384%2Fpost%2FJTslUQaFAm0y4KVP.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fximg%2Fimage%2Fupload%2Fw_732%2Ch_500%2Cc_limit%2Ff_auto%2Fwhoami%2F4a595384%2Fpost%2FJTslUQaFAm0y4KVP.png" width="732" height="151"&gt;&lt;/a&gt;Disable cache and Preserve logs&lt;/p&gt;

&lt;h3&gt;
  
  
  5: Take screenshots directly from the developer console
&lt;/h3&gt;

&lt;p&gt;Chrome devtools has a built-in screenshot tool. To use it type the &lt;code&gt;ctrl+shift+p&lt;/code&gt; (with the devtools window open), then type 'screenshot'.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fximg%2Fimage%2Fupload%2Fw_732%2Ch_500%2Cc_limit%2Ff_auto%2Fwhoami%2F4a595384%2Fpost%2FRRweXfbwwRnulZEo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fximg%2Fimage%2Fupload%2Fw_732%2Ch_500%2Cc_limit%2Ff_auto%2Fwhoami%2F4a595384%2Fpost%2FRRweXfbwwRnulZEo.png" width="732" height="417"&gt;&lt;/a&gt;Take screenshots directly from the developer tools&lt;/p&gt;

&lt;h3&gt;
  
  
  6: There is more to logging than console.log
&lt;/h3&gt;

&lt;p&gt;We all use console.log for debug output, but you have a few more options:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;console.warn, console.error&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;code&gt;console.warn&lt;/code&gt; prints out a different coloured message, and you can filter the log levels.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fximg%2Fimage%2Fupload%2Fw_732%2Ch_500%2Cc_limit%2Ff_auto%2Fwhoami%2F4a595384%2Fpost%2FQq3qtCDFfPTvQas4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fximg%2Fimage%2Fupload%2Fw_732%2Ch_500%2Cc_limit%2Ff_auto%2Fwhoami%2F4a595384%2Fpost%2FQq3qtCDFfPTvQas4.png" width="436" height="171"&gt;&lt;/a&gt;console.warn, console.error&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;console.table&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If you have a structed list of data &lt;code&gt;console.table&lt;/code&gt; will print it in a pretty table format.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fximg%2Fimage%2Fupload%2Fw_732%2Ch_500%2Cc_limit%2Ff_auto%2Fwhoami%2F4a595384%2Fpost%2F93nnpUj0LRAz8NJk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fximg%2Fimage%2Fupload%2Fw_732%2Ch_500%2Cc_limit%2Ff_auto%2Fwhoami%2F4a595384%2Fpost%2F93nnpUj0LRAz8NJk.png" width="732" height="226"&gt;&lt;/a&gt;console.table(data)&lt;/p&gt;

&lt;p&gt;There are several more such as &lt;code&gt;console.assert&lt;/code&gt;, &lt;code&gt;console.group&lt;/code&gt;, you can see the rest &lt;a href="https://developers.google.com/web/tools/chrome-devtools/console/log" rel="noopener noreferrer"&gt;here&lt;/a&gt;:&lt;/p&gt;

&lt;h3&gt;
  
  
  7: $_ returns the most recently evaluated expression
&lt;/h3&gt;

&lt;p&gt;Use &lt;code&gt;$_&lt;/code&gt; to reference the return value of the previous operation executed in the console.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fximg%2Fimage%2Fupload%2Fw_732%2Ch_500%2Cc_limit%2Ff_auto%2Fwhoami%2F4a595384%2Fpost%2FjtJL0I0AdDsv0GNj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fximg%2Fimage%2Fupload%2Fw_732%2Ch_500%2Cc_limit%2Ff_auto%2Fwhoami%2F4a595384%2Fpost%2FjtJL0I0AdDsv0GNj.png" width="399" height="129"&gt;&lt;/a&gt;$_&lt;/p&gt;

&lt;h3&gt;
  
  
  8: $ is a shortcut for document.querySelector
&lt;/h3&gt;

&lt;p&gt;You can use &lt;code&gt;$&lt;/code&gt; to quickly select elements from the console, without jquery.&lt;br&gt;Similarly &lt;code&gt;$$&lt;/code&gt; is a shortcut for &lt;code&gt;document.querySelectorAll&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fximg%2Fimage%2Fupload%2Fw_732%2Ch_500%2Cc_limit%2Ff_auto%2Fwhoami%2F4a595384%2Fpost%2FIAwgvtL7sWilM0ta.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fximg%2Fimage%2Fupload%2Fw_732%2Ch_500%2Cc_limit%2Ff_auto%2Fwhoami%2F4a595384%2Fpost%2FIAwgvtL7sWilM0ta.png" width="426" height="103"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  9: Trigger hover or focus state in styles panel
&lt;/h3&gt;

&lt;p&gt;Hover states can be tricky to inspect since you have to move your mouse over the element, but there is an easy way:  Under Styles, you can force an element style.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fximg%2Fimage%2Fupload%2Fw_732%2Ch_500%2Cc_limit%2Ff_auto%2Fwhoami%2F4a595384%2Fpost%2FH1vM1tK7MPRsQEpB.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fximg%2Fimage%2Fupload%2Fw_732%2Ch_500%2Cc_limit%2Ff_auto%2Fwhoami%2F4a595384%2Fpost%2FH1vM1tK7MPRsQEpB.png" width="441" height="138"&gt;&lt;/a&gt;Force certain element states&lt;/p&gt;

&lt;h3&gt;
  
  
  10: Ctrl+click to find where a CSS property is defined
&lt;/h3&gt;

&lt;p&gt;Ever wondered exactly where a certain css rule was defined?  That is easy to find out, you can simply ctrl+click (cmd+click on a Mac) on the rule.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fximg%2Fimage%2Fupload%2Fw_732%2Ch_500%2Cc_limit%2Ff_auto%2Fwhoami%2F4a595384%2Fpost%2FhcLoRKwIEL4uxlu4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fximg%2Fimage%2Fupload%2Fw_732%2Ch_500%2Cc_limit%2Ff_auto%2Fwhoami%2F4a595384%2Fpost%2FhcLoRKwIEL4uxlu4.png" width="732" height="362"&gt;&lt;/a&gt;Ctrl+click takes you to where the css rule was defined&lt;/p&gt;

&lt;p&gt;Do you have any other DevTools tips?  let me know in the comments :)&lt;/p&gt;

&lt;p&gt;&lt;small&gt;This post was originally published at &lt;a href="https://loftie.com/post/things-you-may-not-know-about-chrome-devtools/" rel="noopener noreferrer"&gt;&lt;/a&gt;&lt;a href="https://loftie.com/post/things-you-may-not-know-about-chrome-devtools/" rel="noopener noreferrer"&gt;https://loftie.com/post/things-you-may-not-know-about-chrome-devtools/&lt;/a&gt;&lt;/small&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>devtools</category>
      <category>chrome</category>
    </item>
    <item>
      <title>Programming Music</title>
      <dc:creator>Loftie Ellis</dc:creator>
      <pubDate>Thu, 19 Sep 2019 22:46:53 +0000</pubDate>
      <link>https://dev.to/lpellis/programming-music-56oi</link>
      <guid>https://dev.to/lpellis/programming-music-56oi</guid>
      <description>&lt;p&gt;What kind of music do you generally prefer for coding?  Personally I find myself looking for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Long (30min+) mixes so I can keep the same tempo going&lt;/li&gt;
&lt;li&gt;No vocals, I find listening to vocals makes it much harder for me to concentrate on coding (others might not be bothered by them)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Below are some of the mixes I enjoy, normally I would just open them in the background on my 2nd monitor (it helps that the visuals are also pleasing without too much going on)&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/l9nh1l8ZIJQ"&gt;
&lt;/iframe&gt;
&lt;br&gt;
&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/4F7sdy2rZws"&gt;
&lt;/iframe&gt;
&lt;br&gt;
&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/kmjiUVEMvI4"&gt;
&lt;/iframe&gt;
&lt;br&gt;
&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/cc3Dofs_j0E"&gt;
&lt;/iframe&gt;
&lt;br&gt;
&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/rr0gvSS1OzE"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Do you have any favourite mixes?  Let me know in the comments.&lt;/p&gt;

</description>
      <category>discuss</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Gridsome 0.7 Released!</title>
      <dc:creator>Loftie Ellis</dc:creator>
      <pubDate>Thu, 19 Sep 2019 18:30:28 +0000</pubDate>
      <link>https://dev.to/lpellis/gridsome-0-7-released-2kn1</link>
      <guid>https://dev.to/lpellis/gridsome-0-7-released-2kn1</guid>
      <description>&lt;p&gt;&lt;a href="https://gridsome.org/" rel="noopener noreferrer"&gt;Gridsome&lt;/a&gt; is a new static site generator based on the JAMstack, and it is the underlying software powering my blog at &lt;a href="https://loftie.com/" rel="noopener noreferrer"&gt;https://loftie.com/&lt;/a&gt;.  If you have ever heard of Gatsby, well Gridsome is the vue.js equivalent, and they just released a new version with some cool improvements.&lt;/p&gt;

&lt;h3&gt;
  
  
  New Schema API
&lt;/h3&gt;

&lt;p&gt;This is be biggest improvement for me.  Gridsome used to simply infer the GraphQL schema from the data passed on startup, which works well if all the data is present, but I started to run into issues where some nested entries (eg tags) were not correctly discovered.  &lt;/p&gt;

&lt;p&gt;With the Schema API you can now define your fields yourself:&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="nx"&gt;api&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;loadSource&lt;/span&gt;&lt;span class="p"&gt;(({&lt;/span&gt; &lt;span class="nx"&gt;addSchemaTypes&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;addSchemaTypes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`
    type Post implements Node {
      title: String
    }
  `&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;You dont have to specify all the fields either, Gridsome can still automatically infer the fields that you know will be present and only specify the deeper ones.  To do that simply pass the &lt;a href="https://gridsome.org/docs/schema-api/#infer" rel="noopener noreferrer"&gt;@infer&lt;/a&gt; extension.&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="nx"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Post&lt;/span&gt; &lt;span class="kr"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;Node&lt;/span&gt; &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;infer&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Other Changes
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Vue Remark plugin - Lets you add vue components to markdown files- &lt;/li&gt;
&lt;li&gt;New template configuration - More consistent way to specify template routes&lt;/li&gt;
&lt;li&gt;Custom App.vue - Useful if you want for example a &lt;code&gt;&amp;lt;transition&amp;gt;&lt;/code&gt; component around the &lt;code&gt;&amp;lt;router-view&amp;gt;&lt;/code&gt;- And some more, see the full list &lt;a href="https://gridsome.org/blog/2019/09/17/gridsome-v07/" rel="noopener noreferrer"&gt;here&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Check out Gridsome for yourself at &lt;a href="https://gridsome.org/" rel="noopener noreferrer"&gt;https://gridsome.org/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>graphql</category>
      <category>vue</category>
    </item>
    <item>
      <title>3 Useful bookmarklets I use (almost) daily</title>
      <dc:creator>Loftie Ellis</dc:creator>
      <pubDate>Mon, 09 Sep 2019 15:57:38 +0000</pubDate>
      <link>https://dev.to/lpellis/3-useful-bookmarklets-i-use-almost-daily-3lm1</link>
      <guid>https://dev.to/lpellis/3-useful-bookmarklets-i-use-almost-daily-3lm1</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;small&gt;&lt;b&gt;Note: &lt;/b&gt;Dev.to doesn't allow javascript in links, so to install these bookmarklets please go to &lt;a href="https://loftie.com/post/3-useful-bookmarklets-i-use-almost-daily" rel="noopener noreferrer"&gt;&lt;/a&gt;&lt;a href="https://loftie.com/post/3-useful-bookmarklets-i-use-almost-daily" rel="noopener noreferrer"&gt;https://loftie.com/post/3-useful-bookmarklets-i-use-almost-daily&lt;/a&gt;&lt;/small&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Bookmarklets are small javascript snippetes that you can use to perform simple tasks.  Below are 3 simple bookmarklets that I find myself using regularly while browsing or doing web development.&lt;/p&gt;

&lt;h3&gt;
  
  
  1: SaneColor
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;Changes the font and background to readable colors&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fximg%2Fimage%2Fupload%2Fw_732%2Ch_500%2Cc_limit%2Ff_auto%2Fwhoami%2F8e65b3bb%2Fpost%2FbNslCUUHuGqNdbb8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fximg%2Fimage%2Fupload%2Fw_732%2Ch_500%2Cc_limit%2Ff_auto%2Fwhoami%2F8e65b3bb%2Fpost%2FbNslCUUHuGqNdbb8.png" width="732" height="64"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Often during browsing or reading articles I get to pages that I find really hard to read due to bad contrast or just hard to read colors. This bookmarklet changes the colors of the background and font to something readable, and works without having to reload the page.&lt;/p&gt;

&lt;h3&gt;
  
  
  2: jQuerify
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;Injects jQuery for usage in the console on any site&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fximg%2Fimage%2Fupload%2Fw_732%2Ch_500%2Cc_limit%2Ff_auto%2Fwhoami%2F8e65b3bb%2Fpost%2Fqv7TL7ighH4DUvCk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fximg%2Fimage%2Fupload%2Fw_732%2Ch_500%2Cc_limit%2Ff_auto%2Fwhoami%2F8e65b3bb%2Fpost%2Fqv7TL7ighH4DUvCk.png" width="350" height="116"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;These days I dont use jQuery as often, but I still find myself wanting to quickly check some things out on a page using its syntax. This bookmarklet makes jQuery available on any page with the click of a button.&lt;/p&gt;

&lt;p&gt;Based on a modified (to work on any site) version of this ancient post: &lt;a href="https://www.learningjquery.com/2009/04/better-stronger-safer-jquerify-bookmarklet" rel="noopener noreferrer"&gt;https://www.learningjquery.com/2009/04/better-stronger-safer-jquerify-bookmarklet&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  3: Make Editable
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;Makes any page editable from the browser&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fximg%2Fimage%2Fupload%2Fw_732%2Ch_500%2Cc_limit%2Ff_auto%2Fwhoami%2F8e65b3bb%2Fpost%2FHdiu8EM9ZyvbRZUY.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fximg%2Fimage%2Fupload%2Fw_732%2Ch_500%2Cc_limit%2Ff_auto%2Fwhoami%2F8e65b3bb%2Fpost%2FHdiu8EM9ZyvbRZUY.png" width="488" height="73"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Often during designing it can be nice to simply edit content directly to see what it would look like. This bookmarklet simply sets &lt;code&gt;contenteditable&lt;/code&gt; for the whole page.&lt;/p&gt;

&lt;p&gt;This can even be useful on pages to remove annoying blinking/distracting elements for the session.&lt;/p&gt;




&lt;p&gt;Do you have any other useful bookmarklets? Let me know in the comments :)&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>productivity</category>
      <category>javascript</category>
    </item>
    <item>
      <title>How to add Twitter and Facebook cards to your vue app</title>
      <dc:creator>Loftie Ellis</dc:creator>
      <pubDate>Sat, 07 Sep 2019 13:05:07 +0000</pubDate>
      <link>https://dev.to/lpellis/how-to-add-twitter-and-facebook-cards-to-your-vue-app-47kl</link>
      <guid>https://dev.to/lpellis/how-to-add-twitter-and-facebook-cards-to-your-vue-app-47kl</guid>
      <description>&lt;p&gt;Adding Twitter/Facebook cards is a great way to improve the experience for when people share your site, and adding it to your vue site only takes a few minutes.&lt;/p&gt;

&lt;h3&gt;
  
  
  What are Twitter Cards?
&lt;/h3&gt;

&lt;p&gt;Have you noticed how some links expand nicely when viewed in Twitter or Facebook?  That functionality is provided by Twitter cards, see an example below:&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1016476808638656521-217" src="https://platform.twitter.com/embed/Tweet.html?id=1016476808638656521"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1016476808638656521-217');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1016476808638656521&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;Tweet with rich content&lt;/p&gt;

&lt;h3&gt;
  
  
  Displaying Twitter/Facebook cards on your site
&lt;/h3&gt;

&lt;p&gt;Twitter and Facebook cards are just special meta tags that you have to include on your site.  When someone then shares your page, Twitter will see those tags and use it to nicely format the post.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Twitter&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The list of twitter tags can be seen &lt;a href="https://developer.twitter.com/en/docs/tweets/optimize-with-cards/overview/abouts-cards" rel="noopener noreferrer"&gt;here&lt;/a&gt;, below I've included the most used ones.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;meta name="twitter:card" content="summary"&amp;gt;
&amp;lt;meta name="twitter:url" content="https://loftie.com"&amp;gt;
&amp;lt;meta name="twitter:title" content="Vue Social Cards Example"&amp;gt;
&amp;lt;meta name="twitter:description" content="Vue sample site showing off Twitter and Facebook Cards."&amp;gt;
&amp;lt;meta name="twitter:image" content="http://dev.to/social_previews/user/139093.png"&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Facebook&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Facebook uses the &lt;a href="https://ogp.me/" rel="noopener noreferrer"&gt;opengraph protocol&lt;/a&gt;, you can see the most used tags below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;meta property="og:type" content="website"&amp;gt;
&amp;lt;meta property="og:title" content="Vue Social Cards Example"&amp;gt;
&amp;lt;meta property="og:description" content="Vue sample site showing off Twitter and Facebook Cards."&amp;gt;
&amp;lt;meta property="og:image" content="http://dev.to/social_previews/user/139093.png"&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Usage in vue
&lt;/h3&gt;

&lt;p&gt;To see how we can setup this in vue, lets first create a basic vue site using the &lt;a href="https://cli.vuejs.org/" rel="noopener noreferrer"&gt;&lt;u&gt;Vue CLI&lt;/u&gt;&lt;/a&gt; with all the default settings.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;vue create vue-sample
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;For a detailed example of how to create a vue site and deploy it to Netlify, please check out &lt;a href="https://loftie.com/post/deploying-vue-with-netlify-from-scratch" rel="noopener noreferrer"&gt;https://loftie.com/post/deploying-vue-with-netlify-from-scratch&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I have deployed the basic version of the site here:  &lt;a href="https://v1--vue-social-cards-sample.netlify.com/" rel="noopener noreferrer"&gt;https://v1--vue-social-cards-sample.netlify.com/&lt;/a&gt;, lets see what happens if we share that to Twitter:&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1170080375835676672-793" src="https://platform.twitter.com/embed/Tweet.html?id=1170080375835676672"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1170080375835676672-793');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1170080375835676672&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;Not very exciting&lt;/p&gt;

&lt;p&gt;To enable cards in vue we need some way to update the meta tags. The most popular way is to use the &lt;a href="https://vue-meta.nuxtjs.org/" rel="noopener noreferrer"&gt;vue-meta&lt;/a&gt; package.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install vue-meta
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then load it in your &lt;code&gt;main.js&lt;/code&gt; file&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import Vue from 'vue';
...
import Meta from 'vue-meta';
Vue.use(Meta);
...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To actually include the relevant meta tags we have to add them to the &lt;code&gt;metaInfo&lt;/code&gt;.  Also note that the image path must be an absolute path, not relative.   &lt;/p&gt;

&lt;p&gt;In this example I'm using the logo.png as the image, and since vue pre-processes all the assets we have to get the path it ends up using &lt;code&gt;require('./assets/logo.png')&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;let ROOT_PATH = 'https://your-site-here.com'
export default {
  data() {
    return {
      logo: ROOT_PATH + require('./assets/logo.png')
    }
  },
  metaInfo() {
    return {
      meta: [
          // Twitter Card
          {name: 'twitter:card', content: 'summary'},
          {name: 'twitter:title', content: 'Vue Social Cards Example'},
          {name: 'twitter:description', content: 'Vue sample site showing off Twitter and Facebook Cards.'},
          // image must be an absolute path
          {name: 'twitter:image', content: this.logo},
          // Facebook OpenGraph
          {property: 'og:title', content: 'Vue Social Cards Example'},
          {property: 'og:site_name', content: 'Vue Example'},
          {property: 'og:type', content: 'website'},
          {property: 'og:image', content:  this.logo},
          {property: 'og:description', content: 'Vue sample site showing off Twitter and Facebook Cards.'}
      ]
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Last steps, prerendering
&lt;/h3&gt;

&lt;p&gt;Currently the meta tags are added using javascript, which is a bit of a problem since the Twitter bot doesn't execute javascript.  Luckily the fix is as simple as clicking a single checkbox if you are using Netlify.&lt;/p&gt;

&lt;p&gt;If you are not using Netlify then you will have to look into other means to prerender, such as &lt;a href="https://prerender.io/" rel="noopener noreferrer"&gt;prerender.io&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In your Netlify account, go to* Site settings -&amp;gt; Build &amp;amp; Deploy -&amp;gt; Prerendering*&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fximg%2Fimage%2Fupload%2Fw_732%2Ch_500%2Cc_limit%2Ff_auto%2Fwhoami%2F4a595384%2Fpost%2FtCG9Uvcv1bbmXvnc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fximg%2Fimage%2Fupload%2Fw_732%2Ch_500%2Cc_limit%2Ff_auto%2Fwhoami%2F4a595384%2Fpost%2FtCG9Uvcv1bbmXvnc.png" width="732" height="282"&gt;&lt;/a&gt;Prerendering allows Twitter and Facebook to see the meta tags&lt;/p&gt;

&lt;p&gt;Lets see how it looks now&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fximg%2Fimage%2Fupload%2Fw_732%2Ch_500%2Cc_limit%2Ff_auto%2Fwhoami%2F8e65b3bb%2Fpost%2FzpdInhkpIMl1C3Z4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fximg%2Fimage%2Fupload%2Fw_732%2Ch_500%2Cc_limit%2Ff_auto%2Fwhoami%2F8e65b3bb%2Fpost%2FzpdInhkpIMl1C3Z4.png" width="523" height="325"&gt;&lt;/a&gt;Much nicer&lt;/p&gt;

&lt;p&gt;The code for this example is available at &lt;a href="https://github.com/lpellis/vue-social-cards-sample" rel="noopener noreferrer"&gt;https://github.com/lpellis/vue-social-cards-sample&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;small&gt;Originally published at &lt;a href="https://loftie.com/post/how-to-add-twitter-and-facebook-cards-to-your-vue-app" rel="noopener noreferrer"&gt;&lt;/a&gt;&lt;a href="https://loftie.com/post/how-to-add-twitter-and-facebook-cards-to-your-vue-app" rel="noopener noreferrer"&gt;https://loftie.com/post/how-to-add-twitter-and-facebook-cards-to-your-vue-app&lt;/a&gt;&lt;/small&gt;&lt;/p&gt;

</description>
      <category>vue</category>
    </item>
  </channel>
</rss>
