<?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: Thomas Rigby</title>
    <description>The latest articles on DEV Community by Thomas Rigby (@hryggrbyr).</description>
    <link>https://dev.to/hryggrbyr</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%2F39835%2Fa4b8ab88-a1fe-4b59-9fa0-547d481119e2.png</url>
      <title>DEV Community: Thomas Rigby</title>
      <link>https://dev.to/hryggrbyr</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/hryggrbyr"/>
    <language>en</language>
    <item>
      <title>Using Zustand to manage application state in React</title>
      <dc:creator>Thomas Rigby</dc:creator>
      <pubDate>Wed, 25 Jan 2023 00:00:00 +0000</pubDate>
      <link>https://dev.to/hryggrbyr/using-zustand-to-manage-application-state-in-react-4l8n</link>
      <guid>https://dev.to/hryggrbyr/using-zustand-to-manage-application-state-in-react-4l8n</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--3N_npyy9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://thomasrigby.com/images/zq6qy6LUu_-300.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--3N_npyy9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://thomasrigby.com/images/zq6qy6LUu_-300.jpeg" alt="A bike, for no reason" width="300" height="212"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;One of the downsides to Controller/Reducer-based state management is that a single piece of state needs to be passed from Component to Component up and down the cascade - &lt;em&gt;regardless of whether that component needs the state or not&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;This can cause an application to run slower than is desirable.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/pmndrs/zustand"&gt;Zustand&lt;/a&gt; promises to alleviate this issue. And, to cut a long story short, it does.&lt;/p&gt;

&lt;p&gt;Observe the &lt;em&gt;Hideous Spaceship&lt;/em&gt; of StateControllers!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ReactDOM.render(
  &amp;lt;React.StrictMode&amp;gt;
    &amp;lt;AppState&amp;gt;
      &amp;lt;UserState&amp;gt;
        &amp;lt;DownloadState&amp;gt;
          &amp;lt;DocumentsState&amp;gt;
            &amp;lt;ShareState&amp;gt;
              &amp;lt;ModalState&amp;gt;
                &amp;lt;ViewerState&amp;gt;
                  &amp;lt;InteractionsState&amp;gt;
                    &amp;lt;NotificationsState&amp;gt;
                      &amp;lt;App /&amp;gt;
                    &amp;lt;/NotificationsState&amp;gt;
                  &amp;lt;/InteractionsState&amp;gt;
                &amp;lt;/ViewerState&amp;gt;
              &amp;lt;/ModalState&amp;gt;
            &amp;lt;/ShareState&amp;gt;
          &amp;lt;/DocumentsState&amp;gt;
        &amp;lt;/DownloadState&amp;gt;
      &amp;lt;/UserState&amp;gt;
    &amp;lt;/AppState&amp;gt;
  &amp;lt;/React.StrictMode&amp;gt;,
  document.getElementById("root")
);

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

&lt;/div&gt;



&lt;p&gt;This means that a piece of information from say &lt;code&gt;ModalState&lt;/code&gt; has to be passed to &lt;code&gt;ViewerState&lt;/code&gt; to &lt;code&gt;InteractionsState&lt;/code&gt; to &lt;code&gt;NotificationsState&lt;/code&gt; before the final destination of &lt;code&gt;&amp;lt;App/&amp;gt;&lt;/code&gt; . This causes several unnecessary re-renders as well as being slow, costly, and frankly irritating.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Zustand&lt;/strong&gt; uses a “Hook-based” approach that doesn’t pass state around components that do not directly need it.&lt;/p&gt;

&lt;p&gt;This approach greatly reduces the “spaceship” and looks a little like this;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ReactDOM.createRoot(document.getElementById('root')).render(
  &amp;lt;React.StrictMode&amp;gt;
    &amp;lt;BrowserRouter&amp;gt;
      &amp;lt;AppRoutes /&amp;gt;
    &amp;lt;/BrowserRouter&amp;gt;
  &amp;lt;/React.StrictMode&amp;gt;
)

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  Creating a Store
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Store/app.jsx

import create from 'zustand'

const useAppStore = create((set, get) =&amp;gt; ({
    openSidebar: () =&amp;gt; set(state =&amp;gt; ({ sidebarIsOpen: true })),
  closeSidebar: () =&amp;gt; set(state =&amp;gt; ({ sidebarIsOpen: false })),
  sidebarIsOpen: false,
});

export default useAppStore;

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

&lt;/div&gt;



&lt;p&gt;Now we have a store we can &lt;code&gt;import&lt;/code&gt; wherever we need to.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Components/Nav.jsx

import useAppStore from '../../Store/app'

const Nav = (
) =&amp;gt; {
  const openSidebar = useAppStore(state =&amp;gt; state.openSidebar)
   return (
    &amp;lt;nav className="primary-nav"&amp;gt;
      &amp;lt;button onClick={openSidebar}&amp;gt;🍔&amp;lt;/button&amp;gt;
      &amp;lt;ul className="nav-list"&amp;gt;...&amp;lt;/ul&amp;gt;
    &amp;lt;/nav&amp;gt;
  )
}

export default Nav


// Components/Sidebar.jsx

import useAppStore from '../../Store/app'

const Sidebar = ({ children }) =&amp;gt; {
  const isSidebarOpen = useAppStore(state =&amp;gt; state.isSidebarOpen)
  const closeSidebar = useAppStore(state =&amp;gt; state.closeSidebar)

  return (
    &amp;lt;aside open={isSidebarOpen} className="sidebar"&amp;gt;
      &amp;lt;button onClick={closeSidebar}&amp;gt;❎&amp;lt;/button&amp;gt;
      {children}
    &amp;lt;/aside&amp;gt;
  )
}

export default Sidebar

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

&lt;/div&gt;



&lt;p&gt;This way, the only Components that are affected by the change in &lt;code&gt;isSidebarOpen&lt;/code&gt; are the &lt;code&gt;Nav&lt;/code&gt; and the &lt;code&gt;Sidebar&lt;/code&gt;. The main body of the app, for example, doesn’t have any knowledge of the state of the sidebar (because it doesn’t &lt;em&gt;need&lt;/em&gt; to know).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Components/Main.jsx

const Main = ({ children }) =&amp;gt; &amp;lt;main&amp;gt;{children}&amp;lt;/main&amp;gt;

export default Main

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

&lt;/div&gt;



&lt;p&gt;However, if we need to, we &lt;em&gt;can&lt;/em&gt; make the &lt;code&gt;Main&lt;/code&gt; aware of the state change as easily as &lt;code&gt;import&lt;/code&gt;ing the Store…&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Components/Main.jsx

import useAppStore from '../../Store/app'

const Main = ({ children }) =&amp;gt; {
  const sidebarIsOpen = useAppStore(state =&amp;gt; state.sidebarIsOpen)
  return &amp;lt;main className={sidebarIsOpen &amp;amp;&amp;amp; 'blur'}&amp;gt;{children}&amp;lt;/main&amp;gt;
}

export default Main

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  Amending state
&lt;/h2&gt;

&lt;p&gt;Imagine, a while down the line, we get the request to track “sidebar opens” (for whatever mad reason - clients, eh?!). The only file we need to change is the Store.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Store/app.jsx

import create from 'zustand'
import Analytics from 'analytics'

const useAppStore = create((set, get) =&amp;gt; ({
    openSidebar: () =&amp;gt; {
    Analytics.log({ event: 'sidebarOpen', timestamp: new Date() })
    set(state =&amp;gt; ({ sidebarIsOpen: true }))
  },
  closeSidebar: () =&amp;gt; set(state =&amp;gt; ({ sidebarIsOpen: false })),
  sidebarIsOpen: false,
});

export default useAppStore;

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;The learning curve is shallow enough - even for someone like me who isn’t the most React-savvy! It makes the state much more readable and replaceable too.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Quick and dirty server 2</title>
      <dc:creator>Thomas Rigby</dc:creator>
      <pubDate>Wed, 07 Sep 2022 00:00:00 +0000</pubDate>
      <link>https://dev.to/hryggrbyr/quick-and-dirty-server-2-3f57</link>
      <guid>https://dev.to/hryggrbyr/quick-and-dirty-server-2-3f57</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--pd2eJr26--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://thomasrigby.com/images/ec4d69a8-300.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--pd2eJr26--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://thomasrigby.com/images/ec4d69a8-300.jpeg" alt="A python" width="300" height="207"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I wrote last year about spinning up a &lt;a href="https://thomasrigby.com/articles/quick-and-dirty-server/"&gt;quick and dirty server&lt;/a&gt; using &lt;a href="https://www.python.org/"&gt;Python&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Since then, I have moved to using Python 3 (woop woop!) and, the first time I ran my funky little &lt;code&gt;srv 1337&lt;/code&gt; function I got an error! 😱&lt;/p&gt;

&lt;h2&gt;
  
  
  "No module named SimpleHTTPServer"
&lt;/h2&gt;

&lt;p&gt;According to the &lt;a href="https://docs.python.org/2/library/simplehttpserver.html"&gt;Python 2.7 documentation&lt;/a&gt;…&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The SimpleHTTPServer module has been merged into http.server in Python 3.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So, the simple-enough solution is to replace &lt;code&gt;SimpleHTTPServer&lt;/code&gt; with &lt;code&gt;http.server&lt;/code&gt;.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Navigate to the folder you want to serve&lt;/li&gt;
&lt;li&gt;&lt;code&gt;python -m http.server&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Open &lt;code&gt;http://localhost:8000&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  What if PORT 8000 is in use?
&lt;/h3&gt;

&lt;p&gt;Pass a different port number like this: &lt;code&gt;python -m http.server %%PORT_NUMBER%%&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;If you want it to be &lt;em&gt;even simpler&lt;/em&gt; - stick this somewhere in your bash config!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;srv() {
  python -m http.server $1
}

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

&lt;/div&gt;



&lt;p&gt;As before, it doesn't come with any of the fancy stuff that other "local server" plugins might come with like hot reloading or compiling Scss but, if all you want is a small static site launching, why reach for another dependency?&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Trim trailing slash</title>
      <dc:creator>Thomas Rigby</dc:creator>
      <pubDate>Thu, 01 Sep 2022 00:00:00 +0000</pubDate>
      <link>https://dev.to/hryggrbyr/trim-trailing-slash-441a</link>
      <guid>https://dev.to/hryggrbyr/trim-trailing-slash-441a</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Os07RNBa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://thomasrigby.com/images/U7wC5ZHbkV-300.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Os07RNBa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://thomasrigby.com/images/U7wC5ZHbkV-300.jpeg" alt="silver scissors on pink surface" width="300" height="200"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Sometimes a URL has a trailing slash, sometimes it doesn't. If we can't be certain, we need to handle either eventuality.&lt;/p&gt;

&lt;h2&gt;
  
  
  Shut up and give me the code!
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const trimTrailingSlash = (x) =&amp;gt; x.split('').reverse()[0] !== '/' ? x : x.substring(0,x.split('').length -1);

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  Let's break that down
&lt;/h2&gt;

&lt;p&gt;First off we're creating an &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions"&gt;arrow function&lt;/a&gt; that will accept an input that we're calling &lt;code&gt;x&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Inside the function, &lt;code&gt;x&lt;/code&gt; is &lt;code&gt;split&lt;/code&gt; into individual characters creating an array. The array is reversed using, well, &lt;code&gt;reverse()&lt;/code&gt;. This means we can check the &lt;em&gt;first&lt;/em&gt; character (&lt;code&gt;[0]&lt;/code&gt;) instead of having to work out what the &lt;em&gt;last&lt;/em&gt; character is - smart!&lt;/p&gt;

&lt;p&gt;If that character does not equal (&lt;code&gt;!==&lt;/code&gt;) a slash simply return the given string. Bouncing out of a function as soon as possible keeps our code quick!&lt;/p&gt;

&lt;p&gt;If the character is a trailing slash, we want to get rid of it; to return part of a string, we can use &lt;code&gt;substring&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Substring takes two parameters: the starting index and the finishing index. We will start at &lt;code&gt;0&lt;/code&gt; which is the very first character and finish with the second to last character (the one before the &lt;code&gt;/&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;To figure what that number is we, again, &lt;code&gt;split&lt;/code&gt; the string into an array and use the total number of items (&lt;code&gt;.length&lt;/code&gt;) minus 1.&lt;/p&gt;

&lt;h2&gt;
  
  
  Alternative solution!
&lt;/h2&gt;

&lt;p&gt;Using &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/endsWith"&gt;&lt;code&gt;String.prototype.endsWith()&lt;/code&gt;&lt;/a&gt; and &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/slice"&gt;&lt;code&gt;String.prototype.slice()&lt;/code&gt;&lt;/a&gt;, we can shorten this function - and make it a little more readable! 🎉&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  const trimTrailingSlash = (x) =&amp;gt; x.endsWith('/') ? x.slice(0,-1) : x;

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

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;.endsWith()&lt;/code&gt; works exactly how you would imagine: if the string &lt;em&gt;ends with&lt;/em&gt; the given character, the method returns &lt;code&gt;true&lt;/code&gt;, otherwise it returns &lt;code&gt;false&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;To trim a trailing slash from a URL requires two operations;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;We must determine if the last character is a slash&lt;/li&gt;
&lt;li&gt;If it is, we must remove the slash&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Each of these steps can be performed in several ways, you can mix-and-match them how you want.&lt;/p&gt;

&lt;p&gt;I've not done any performance testing on these so I couldn't tell you which is fastest when trimming the trailing slash from 40,000 URLs but, unless you &lt;em&gt;are&lt;/em&gt; working with 40,000 URLs, just pick the one you feel is the most readable.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>How to create a global .gitignore file</title>
      <dc:creator>Thomas Rigby</dc:creator>
      <pubDate>Fri, 06 Aug 2021 00:00:00 +0000</pubDate>
      <link>https://dev.to/hryggrbyr/how-to-create-a-global-gitignore-file-5g3b</link>
      <guid>https://dev.to/hryggrbyr/how-to-create-a-global-gitignore-file-5g3b</guid>
      <description>&lt;p&gt;Unfortunately, this has happened to the best of us at some point, amirite?!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--dpbiokO1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vli86byoexfsgppa328o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--dpbiokO1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vli86byoexfsgppa328o.png" alt="Screenshot of GitKraken showing a new git ignore file and 30,383 deleted files in the node modules folder" width="199" height="63"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Inspired by this monstrosity, I decided to do some investigation!&lt;/p&gt;

&lt;p&gt;Here is how to create a global &lt;code&gt;.gitignore&lt;/code&gt; file to define a list of rules for ignoring files in &lt;em&gt;&lt;strong&gt;every single&lt;/strong&gt;&lt;/em&gt; Git repository on your computer…&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
  touch ~/.gitignore_global
  echo node_modules &amp;gt;&amp;gt; ~/.gitignore_global
  echo .DS_Store &amp;gt;&amp;gt; ~/.gitignore_global
  echo .vscode &amp;gt;&amp;gt; ~/.gitignore_global
  git config --global core.excludesfile ~/.gitignore_global

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

&lt;/div&gt;



&lt;p&gt;For more handy git tips: &lt;a href="https://docs.github.com/en/get-started/getting-started-with-git/ignoring-files#configuring-ignored-files-for-all-repositories-on-your-computer"&gt;RTFM 😉&lt;/a&gt;&lt;/p&gt;

</description>
      <category>git</category>
    </item>
    <item>
      <title>WordPress forgotten password localhost hack</title>
      <dc:creator>Thomas Rigby</dc:creator>
      <pubDate>Fri, 11 Jun 2021 00:00:00 +0000</pubDate>
      <link>https://dev.to/hryggrbyr/wordpress-forgotten-password-localhost-hack-4aj5</link>
      <guid>https://dev.to/hryggrbyr/wordpress-forgotten-password-localhost-hack-4aj5</guid>
      <description>&lt;p&gt;I have lost count of the number of times I've forgotten the password to the local or development CMS.&lt;/p&gt;

&lt;p&gt;My natural instinct is to click the &lt;em&gt;Forgot Password&lt;/em&gt; link but, obviously, there's no way to trigger that email from the local system.&lt;/p&gt;

&lt;p&gt;I've spent too long hunting through articles on how to recover the forgotten password. The quickest and easiest solution that I've found is to change the password manually in the database.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--rn99R_Lv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lwoq5ndminw5a4saboai.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--rn99R_Lv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lwoq5ndminw5a4saboai.jpg" alt="A hacker wearing an Anonymous mask hacks into a WordPress blog. Possibly." width="800" height="1005"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How do we do that then?
&lt;/h2&gt;

&lt;p&gt;WordPress stores passwords in the &lt;code&gt;wp_users&lt;/code&gt; table. The prefix may be different if you have elected to change that in the &lt;code&gt;wp-config.php&lt;/code&gt; file. It's good practice to do that for security.&lt;/p&gt;

&lt;p&gt;When you look at the table, it'll look a little like this…&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;ID&lt;/th&gt;
&lt;th&gt;user_login&lt;/th&gt;
&lt;th&gt;user_pass&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;thomasxbanks&lt;/td&gt;
&lt;td&gt;$P$BHpcLw/aWsTPmeDprzXwOEl45bJm9A3&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;WordPress stores your password as an &lt;a href="https://en.wikipedia.org/wiki/MD5"&gt;MD5 hashed string&lt;/a&gt;&lt;sup&gt;*&lt;/sup&gt;. This prevents anyone with access to the database seeing confidential information in plain text.&lt;/p&gt;

&lt;p&gt;If this &lt;em&gt;wasn't&lt;/em&gt; obfuscated like this, we'd be able to copy our password and paste it into the login form…but we can't - and for good reason!&lt;/p&gt;

&lt;p&gt;So, to fix our little problem, we need to replace the existing hashed password with a new hashed password - we can't overwrite the MD5 hash with plain text because that won't work.&lt;/p&gt;

&lt;p&gt;I have &lt;a href="https://marketplace.visualstudio.com/items?itemName=deerawan.vscode-hasher"&gt;Hasher&lt;/a&gt; installed as a plugin in VS Code. If you don't use VS Code or don't want to use this extension, &lt;a href="https://www.md5hashgenerator.com/"&gt;MD5 Hash Generator Online&lt;/a&gt; works pretty well.&lt;/p&gt;

&lt;p&gt;I would recommend that you don't create your "forever password" using these hash generators though. Overwrite the existing password with something easy to remember and &lt;strong&gt;very, very temporary&lt;/strong&gt; - a favourite of mine is &lt;code&gt;Pa55word!&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;267057150e34eca5c6af39ec9b30864e
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once the password has been changed, you can log in with your new password &lt;strong&gt;and immediately change it to something more secure&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;I hope this helps you as much as it has helped me. 😎&lt;/p&gt;




&lt;p&gt;&lt;sup&gt;*&lt;/sup&gt; As pointed out by &lt;a href="https://dev.to/sorinmarta"&gt;@sorinmarta&lt;/a&gt; in the comments, WordPress salts the password using PHPass (as you can see from the &lt;code&gt;$P$&lt;/code&gt; at the start of the example password). This hack will still work though as, even if your password has been salted, &lt;a href="https://wordpress.org/support/article/resetting-your-password/"&gt;you can still replace the password with an MD5 hash, and WordPress will let you log in&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>wordpress</category>
      <category>password</category>
      <category>security</category>
    </item>
    <item>
      <title>Semantic HTML</title>
      <dc:creator>Thomas Rigby</dc:creator>
      <pubDate>Fri, 11 Jun 2021 00:00:00 +0000</pubDate>
      <link>https://dev.to/hryggrbyr/semantic-html-4ooi</link>
      <guid>https://dev.to/hryggrbyr/semantic-html-4ooi</guid>
      <description>&lt;p&gt;Semantic HTML is the process of using HTML5 tags to reinforce the meaning of the information contained within a webpage or application.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/HTML5"&gt;HTML5&lt;/a&gt; was introduced in October 2014 and introduced several new element tags to provide &lt;em&gt;explicit&lt;/em&gt; meaning to the content of a website. And, as all websites are &lt;em&gt;nothing more&lt;/em&gt; than a means for conveying content, this is the most important foundation for any site.&lt;/p&gt;

&lt;p&gt;Bluntly, semantic HTML says what an element is instead of using a &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt; for everything.&lt;/p&gt;

&lt;h2&gt;
  
  
  Div Soup™️
&lt;/h2&gt;

&lt;p&gt;Consider this piece of code…&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="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"article"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;img&lt;/span&gt; &lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"image"&lt;/span&gt; &lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;image&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt; &lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"h1"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&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="na"&gt;class&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"content"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;excerpt&lt;/span&gt;&lt;span class="si"&gt;}&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;
  &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;categories&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;category&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&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="na"&gt;class&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"category-tag"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;category&lt;/span&gt;&lt;span class="si"&gt;}&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;&lt;span class="si"&gt;}&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;

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

&lt;/div&gt;



&lt;p&gt;While this is not an unacceptable way of using markup to describe a group of elements, it could also be confusing for a number of reasons.&lt;/p&gt;

&lt;p&gt;We spend considerably more time reading code than writing it. A lot of us do not have the luxury of solely working with familiar code; we work in teams with several developers working on the same codebase or in agencies working with multiple codebases - some a lot older or less maintained.&lt;/p&gt;

&lt;p&gt;While we read, much like users on a webpage do, we use an &lt;a href="https://www.nngroup.com/articles/f-shaped-pattern-reading-web-content/"&gt;F pattern&lt;/a&gt;. This means we’re basically scanning down the left-hand edge of the code to get a gist of what we’re dealing with.&lt;/p&gt;

&lt;p&gt;The code above reads very much like “div, img, h1, div, div, div…”&lt;/p&gt;

&lt;h2&gt;
  
  
  Semantic markup
&lt;/h2&gt;

&lt;p&gt;Now consider this refactored code…&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="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;article&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;header&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;figure&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;img&lt;/span&gt; &lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;image&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;alt&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;image&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;alt&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;figure&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;header&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&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;
    &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;excerpt&lt;/span&gt;&lt;span class="si"&gt;}&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;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;footer&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;ul&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;categories&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;category&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;category&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;ul&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;footer&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;article&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Now the code above reads like “article, header, div, footer”.&lt;/p&gt;

&lt;p&gt;In all honesty, it does require more markup than the previous example but, on the other hand, when we scan the code we can clearly see that this is an article with a header image and a title - there is a main body to the article, followed by a list of categories.&lt;/p&gt;

&lt;h2&gt;
  
  
  Accessibility
&lt;/h2&gt;

&lt;p&gt;Your browser will scan through your website's DOM and decide if each node it encounters is useful and, if so, will add it to the Accessibility Tree.&lt;/p&gt;

&lt;p&gt;Screen-readers and other assistive technologies then use the Accessibility Tree instead of the visual UI of your website.&lt;/p&gt;

&lt;p&gt;The browser can better determine whether something should go in the Accessibility Tree if it can understand what the node is for - which is where semantics come in.&lt;/p&gt;

&lt;p&gt;Browsers will happily ignore &lt;code&gt;div&lt;/code&gt;s and &lt;code&gt;span&lt;/code&gt;s because they semantically mean nothing - they're for visual layout and the Accessibility Tree cares not for visual layout!&lt;/p&gt;

&lt;p&gt;Of course you could always pepper your &lt;code&gt;div&lt;/code&gt;s with &lt;code&gt;role="button"&lt;/code&gt; or whatever but that goes against &lt;a href="https://www.w3.org/TR/wai-aria-1.2/"&gt;WAI-ARIA recommendations&lt;/a&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;It is not appropriate to create objects with style and script when the host language provides a semantic element for that type of object. While WAI-ARIA can improve the accessibility of these objects, accessibility is best provided by allowing the user agent to handle the object natively. For example, it's better to use an &lt;code&gt;h1&lt;/code&gt; element in HTML than to use the &lt;code&gt;heading&lt;/code&gt; role on a &lt;code&gt;div&lt;/code&gt; element.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  SEO
&lt;/h2&gt;

&lt;p&gt;Semantic HTML is not only for developers and screen readers - it also helps search engines crawl your content.&lt;/p&gt;

&lt;p&gt;Don't take my word for it - &lt;a href="https://developer.yoast.com/blog/why-your-websites-code-structure-matters/"&gt;Yoast recommends using semantic markup to improve ranking&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;We can improve on this even further by layering in &lt;a href="http://schema.org/"&gt;Schema data&lt;/a&gt;.&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="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;article&lt;/span&gt; &lt;span class="na"&gt;itemscope&lt;/span&gt; &lt;span class="na"&gt;itemtype&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"http://schema.org/Article"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;header&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;figure&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;img&lt;/span&gt; &lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;image&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;alt&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;image&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;alt&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;itemprop&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"image"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;figure&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt; &lt;span class="na"&gt;itemprop&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"headline"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;header&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&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="na"&gt;itemprop&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"articleBody"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;excerpt&lt;/span&gt;&lt;span class="si"&gt;}&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;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;footer&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;ul&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;categories&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;category&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt; &lt;span class="na"&gt;itemprop&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"articleSection"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;category&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;ul&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;footer&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;article&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Using semantic HTML and Schema data to define your structure means it’s quicker and more accurate for search bots to index your content because they don’t have to make assumptions about what something is.&lt;/p&gt;

&lt;h2&gt;
  
  
  Violent Psychopaths
&lt;/h2&gt;

&lt;p&gt;Another benefit is that it becomes clearer for the next developer (even if that is you in the future) who will maintain this code.&lt;/p&gt;

&lt;p&gt;It is a known fact that any code you wrote six months ago might as well have been written by someone else. 😉&lt;/p&gt;

&lt;p&gt;Using semantic HTML also goes towards your separation of concerns, keeping the “structure” and the “design” separate. Ensuring the markup describes the structure, leaving the css to describe the appearance will make things easier to adjust and maintain going forward.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Always code as if the guy who ends up maintaining your code will be a violent psychopath who knows where you live.&lt;/p&gt;

&lt;p&gt;&lt;cite&gt;&lt;a href="https://groups.google.com/g/comp.lang.c++/c/rYCO5yn4lXw/m/oITtSkZOtoUJ"&gt;John F Woods, 1991&lt;/a&gt;&lt;/cite&gt;&lt;/p&gt;
&lt;/blockquote&gt;

</description>
    </item>
    <item>
      <title>I am a lazy developer or How to write 438 lines of nginx redirects</title>
      <dc:creator>Thomas Rigby</dc:creator>
      <pubDate>Mon, 07 Jun 2021 00:00:00 +0000</pubDate>
      <link>https://dev.to/hryggrbyr/i-am-a-lazy-developer-or-how-to-write-438-lines-of-nginx-redirects-4bim</link>
      <guid>https://dev.to/hryggrbyr/i-am-a-lazy-developer-or-how-to-write-438-lines-of-nginx-redirects-4bim</guid>
      <description>&lt;p&gt;When I say "I am a lazy developer", I don't mean to imply that I cut corners and churn out shoddy code. I just hate doing repetitive tasks that bore the bejesus out of me!&lt;/p&gt;

&lt;p&gt;Obviously, I'm not alone in this - it's the reason &lt;a href="https://www.smashingmagazine.com/2016/06/harness-machines-productive-task-runners/"&gt;task runners&lt;/a&gt; exist.&lt;/p&gt;

&lt;p&gt;Recently, at work, I replatformed an existing e-commerce site which resulted in, amongst other things, a giant list of redirects from existing urls to the new url structure.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://moz.com/learn/seo/redirection"&gt;Permanent redirects (301s for the people who like numbers) are essential for persistence of good SEO&lt;/a&gt;. The downside is adding the old url and the new url to the line &lt;code&gt;rewrite ^/&amp;lt;oldlocation&amp;gt;$ &amp;lt;newlocation&amp;gt; permanent;&lt;/code&gt; in my nginx config file. What's a lazy guy to do when you have to do this 438 times…?&lt;/p&gt;

&lt;p&gt;Well, this immediately looks like a case for loops and variables!&lt;/p&gt;

&lt;h2&gt;
  
  
  How can &lt;em&gt;you&lt;/em&gt; do this wizardry?!
&lt;/h2&gt;

&lt;p&gt;You'll need four things;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;a href="https://nodejs.org/en/"&gt;NodeJS&lt;/a&gt; installed on your machine,&lt;/li&gt;
&lt;li&gt;a command-line application like Hyper, iTerm2, or Terminal,&lt;/li&gt;
&lt;li&gt;a CSV file of the required redirects, and&lt;/li&gt;
&lt;li&gt;this handy class in an &lt;code&gt;index.js&lt;/code&gt; file.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// excel.csv

old,new
https://thomasxbanks.com/newyork/, https://thomasxbanks.com/locations/newyork/
https://thomasxbanks.com/paris/, https://thomasxbanks.com/locations/paris/
https://thomasxbanks.com/peckham/, https://thomasxbanks.com/locations/peckham/


// index.js

const fs = require('fs');

class GenerateNginxRedirectsFromCSV {
  constructor(input, output) {
    this.input = input || './input.csv';
    this.output = output || './output.txt';
    this.csv = null;
    this.results = [];
  }

  async read() {
    this.csv = await fs.readFileSync(this.input, { encoding: 'utf8', flag: 'r' });
  }

  async format() {
    this.results = this.csv.replace(/\n/g, '').split('\r').filter(Boolean).slice(1).map((x) =&amp;gt; `rewrite ^/${x.split(',')[0]}?$ ${x.split(',')[1]} permanent;\n` );
  }

  write() {
    this.results.forEach(async (value) =&amp;gt; {
      await fs.appendFileSync(this.output, value);
    });
  }

  async init() {
    await this.read();
    await this.format();
    await this.write();
  }
}

const task = new GenerateNginxRedirectsFromCSV('./excel.csv', './redirects.txt');
task.init();

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

&lt;/div&gt;



&lt;p&gt;Put both files in the same folder, open the folder in your command line Terminal application and run &lt;code&gt;node ./&lt;/code&gt;. This will generate a file (called &lt;code&gt;output.txt&lt;/code&gt; unless you've changed it) listing your redirects in an easy-to-copypasta format. Paste the contents into your &lt;code&gt;nginx.conf&lt;/code&gt; file.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cool! How does it work?
&lt;/h2&gt;

&lt;p&gt;There's a lot going on here so let's go through it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const fs = require('fs');

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

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://nodejs.org/api/fs.html"&gt;fs&lt;/a&gt; is the NodeJS File System module. I won't go into detail here but, basically, it allows you to &lt;em&gt;Read from&lt;/em&gt; and &lt;em&gt;Write to&lt;/em&gt; files on your local system, servers, or whereever Node is installed.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;constructor(input, output) {
  this.input = input || './input.csv';
  this.output = output || './output.txt';
  this.csv = '';
  this.results = [];
}

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

&lt;/div&gt;



&lt;p&gt;In the constructor, we set our scoped variables (including fallbacks) and the empty variables that will be populated by our fetched and formatted data.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;async init() {
  await this.read();
  await this.format();
  await this.write();
}

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

&lt;/div&gt;



&lt;p&gt;As we can see from the &lt;code&gt;init()&lt;/code&gt; function, our three basic steps are;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Get the contents of the CSV file&lt;/li&gt;
&lt;li&gt;Convert it into a format nginx can understand&lt;/li&gt;
&lt;li&gt;Write the results to a file&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Step 1 - Get the contents of the CSV
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;this.csv = await fs.readFileSync(this.input, { encoding: 'utf8', flag: 'r' });

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

&lt;/div&gt;



&lt;p&gt;Read the input filepath and save the contents into the &lt;code&gt;this.csv&lt;/code&gt; variable for later use.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2 - Convert CSV to nginx
&lt;/h3&gt;

&lt;p&gt;Since the output of the csv file is consistent, and so is the format of a JSON object, we can map one to the other.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;async format() {
  this.results = this.csv.replace(/\n/g, '').split('\r').filter(Boolean).slice(1).map((x) =&amp;gt; `rewrite ^/${x.split(',')[0]}?$ ${x.split(',')[1]} permanent;\n` );
}

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

&lt;/div&gt;



&lt;p&gt;Firstly, replace any &lt;code&gt;\n&lt;/code&gt; line-endings, then explode the string into an array at each line-break (&lt;code&gt;\r&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Then, we generate an array of results.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Filter out any empty lines with &lt;code&gt;.filter(Boolean)&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Remove the line with the headers using &lt;code&gt;.slice(1)&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;For each remaining line, generate a string to copy into &lt;code&gt;nginx.conf&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It should look a little like this;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;rewrite ^/https://thomasxbanks.com/newyork/?$ https://thomasxbanks.com/locations/newyork/ permanent;

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 3 - Write the output file
&lt;/h3&gt;

&lt;p&gt;Now that &lt;code&gt;this.results&lt;/code&gt; is an array of strings, we can&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;loop through each instance&lt;/li&gt;
&lt;li&gt;insert the result to an ouput file using &lt;em&gt;fs&lt;/em&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All that's left to do is open the resulting file and copypasta the content into your &lt;code&gt;nginx.conf&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;Don't forget to gracefully restart the nginx server. Forgetting this has caused me untold headaches!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;nginx -t &amp;amp;&amp;amp; nginx service restart
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Now, I'm sure there are &lt;del&gt;different&lt;/del&gt; better ways to do this but, off the top of my head, this seemed quick and simple enough to whip together.&lt;/p&gt;

&lt;p&gt;I've no idea how long it would have taken me to manually do this but I'm certain it would have taken longer than to write this bit of code.&lt;/p&gt;

&lt;p&gt;Not only did I save myself time on that particular day, whenever I (or someone else on my team) need to do this again I have a useful tool to reuse again and again 😎&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>nginx</category>
      <category>redirects</category>
      <category>utility</category>
    </item>
    <item>
      <title>You have a better laptop than your users</title>
      <dc:creator>Thomas Rigby</dc:creator>
      <pubDate>Thu, 20 May 2021 00:00:00 +0000</pubDate>
      <link>https://dev.to/hryggrbyr/you-have-a-better-laptop-than-your-users-29j0</link>
      <guid>https://dev.to/hryggrbyr/you-have-a-better-laptop-than-your-users-29j0</guid>
      <description>&lt;p&gt;I have a fairly decent laptop provided by my employer and I'm lucky enough to have a strong, reliable internet connection. Not everyone does. I'll say that again for the Bro's at the back:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Not all of your users will have a top-spec device and good wifi like you do.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In the past I've been guilty of assuming that everyone has a comparable experience to myself.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;This leads to Bad Habits™️.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How to be better
&lt;/h2&gt;

&lt;p&gt;Optimise for performance over appearance. Basically, don't make someone download 5Gb of images and 500Mb of JavaScript just to read your Terms &amp;amp; Conditions page.&lt;/p&gt;

&lt;p&gt;Test on spotty wifi. Try using the site on a train or in a coffee shop or using the City's free wifi (if you have it where you are). This is how your user will experience your site - not via 100Gb Ethernet cables.&lt;/p&gt;

&lt;p&gt;Test on budget devices - find a few common mid-priced devices (you could probably get them from &lt;a href="https://www.ebay.co.uk/sch/i.html?_from=R40&amp;amp;_trksid=p2334524.m570.l1313&amp;amp;_nkw=iphone+7&amp;amp;_sacat=0&amp;amp;LH_TitleDesc=0&amp;amp;_osacat=0&amp;amp;_odkw=iphone+7"&gt;eBay&lt;/a&gt;) and test on those instead.&lt;/p&gt;

&lt;p&gt;If you're feeling extra spicy - make sure at least one of those devices has a cracked screen for a truly authentic browsing experience 😜&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>testing</category>
      <category>qa</category>
      <category>a11y</category>
    </item>
    <item>
      <title>Generate a random alphanumeric string using JavaScript</title>
      <dc:creator>Thomas Rigby</dc:creator>
      <pubDate>Thu, 29 Apr 2021 00:00:00 +0000</pubDate>
      <link>https://dev.to/hryggrbyr/generate-a-random-alphanumeric-string-using-javascript-52nn</link>
      <guid>https://dev.to/hryggrbyr/generate-a-random-alphanumeric-string-using-javascript-52nn</guid>
      <description>&lt;p&gt;Today I had to send an "&lt;code&gt;ID&lt;/code&gt;" in the body of my POST request. It turns out that the API doesn't care what the value is - it just needs to be alphanumeric (a-z, A-Z, 0-9), exactly 18 characters long, and not already in the system.&lt;/p&gt;

&lt;p&gt;So I decided to generate a random string&lt;sup&gt;*&lt;/sup&gt;!&lt;/p&gt;

&lt;h2&gt;
  
  
  Shut up already and give me the code!
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;randomString&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;len&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;len&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;fill&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ceil&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;random&lt;/span&gt;&lt;span class="p"&gt;()).&lt;/span&gt;&lt;span class="nx"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;36&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;charAt&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="nx"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Boolean&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;sort&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;random&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mf"&gt;0.5&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toUpperCase&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;join&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="nx"&gt;substr&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="nx"&gt;len&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Now, let's break that down!
&lt;/h2&gt;

&lt;p&gt;There's a lot going on in that one line!&lt;/p&gt;

&lt;p&gt;Firstly, we create an &lt;code&gt;Array&lt;/code&gt; with twice as many "characters" as we need.&lt;/p&gt;

&lt;p&gt;Then we &lt;code&gt;fill&lt;/code&gt; each item in the array with the number 1000.&lt;/p&gt;

&lt;p&gt;For each of those items (&lt;code&gt;.map()&lt;/code&gt;), we randomise the number by multiplying it by a randomly generated number between 0 and 1 (&lt;code&gt;x * Math.random()&lt;/code&gt;). This is then converted into a two-character string. We only need the first character so let's grab that with &lt;code&gt;charAt(0)&lt;/code&gt;. You could also use &lt;code&gt;[0]&lt;/code&gt; as shorthand.&lt;/p&gt;

&lt;p&gt;Now we have an Array of twice as many random alphanumeric characters as we asked for.&lt;/p&gt;

&lt;p&gt;Just to be on the safe side, we remove any empty or falsey values using &lt;code&gt;.filter(Boolean)&lt;/code&gt; - this will get rid of any zeroes but meh 🤷‍♀️&lt;/p&gt;

&lt;p&gt;The remaining values are shuffled into a new random order with &lt;code&gt;.sort(() =&amp;gt; Math.random() - 0.5)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Our new array is then looped through again and every even-index character is UPPERCASED (if possible - the numbers 0 to 9 cannot be uppercased).&lt;/p&gt;

&lt;p&gt;Now we have an array of much more random characters, but this is &lt;code&gt;randomString&lt;/code&gt; - what use is an array?! We need to &lt;code&gt;join('')&lt;/code&gt; the array together. The &lt;code&gt;''&lt;/code&gt; separator is necessary - without it our string would be full of commas - gross!&lt;/p&gt;

&lt;p&gt;Finally, remember how the string is twice as long as we need? - we return the correct number of characters from the start of the string.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;So there it is! I have no idea how well it performs but you probably shouldn't be generating random strings in production anyway! 😬&lt;/p&gt;

&lt;p&gt;What's this is probably most useful for is playing around with the individual components it's made up of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Fill: &lt;code&gt;Array.fill()&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Shuffle: &lt;code&gt;Array.sort(() =&amp;gt; Math.random() - 0.5)&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Modulos: &lt;code&gt;i % 2 === 0&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Remove 'falsey' values: &lt;code&gt;Array.filter(Boolean)&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
  &lt;span&gt;See the Pen &lt;a href="https://codepen.io/thomasxbanks/pen/ExZGEKQ"&gt;
  Generate a random Alphanumeric String using JavaScript&lt;/a&gt; by thomas×banks (ツ) (&lt;a href="https://codepen.io/thomasxbanks"&gt;@thomasxbanks&lt;/a&gt;)
  on &lt;a href="https://codepen.io"&gt;CodePen&lt;/a&gt;.&lt;/span&gt;
&lt;/p&gt;

&lt;p&gt;&lt;sup&gt;*&lt;/sup&gt; A better solution to this problem is…&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;btoa&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;()).&lt;/span&gt;&lt;span class="nx"&gt;substr&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;18&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;…but where's the fun in that?! 😈&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>random</category>
    </item>
    <item>
      <title>Wait!</title>
      <dc:creator>Thomas Rigby</dc:creator>
      <pubDate>Mon, 19 Apr 2021 17:32:00 +0000</pubDate>
      <link>https://dev.to/hryggrbyr/wait-2ibp</link>
      <guid>https://dev.to/hryggrbyr/wait-2ibp</guid>
      <description>&lt;p&gt;Why the rush…?!&lt;/p&gt;

&lt;p&gt;Whether you're faking an API response, introducing deliberate cognitive drain, or simply want to slow things down this utility function has got you, baby! 😎&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;delay&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ms&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;rv&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;rv&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ms&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Cool! How do I use it?
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`hello world`&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nice! Does it work with &lt;code&gt;async/await&lt;/code&gt;?&lt;/p&gt;

&lt;p&gt;Heck, yes, it does!&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;functionName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async&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="nx"&gt;doFirstThing&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="nx"&gt;doNextThing&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;
  &lt;span&gt;See the Pen &lt;a href="https://codepen.io/thomasxbanks/pen/wvoVwXL"&gt;
  Delay&lt;/a&gt; by thomas×banks (ツ) (&lt;a href="https://codepen.io/thomasxbanks"&gt;@thomasxbanks&lt;/a&gt;)
  on &lt;a href="https://codepen.io"&gt;CodePen&lt;/a&gt;.&lt;/span&gt;
&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>utility</category>
    </item>
    <item>
      <title>Quick and dirty carousel</title>
      <dc:creator>Thomas Rigby</dc:creator>
      <pubDate>Tue, 13 Apr 2021 00:00:00 +0000</pubDate>
      <link>https://dev.to/hryggrbyr/quick-and-dirty-carousel-11bl</link>
      <guid>https://dev.to/hryggrbyr/quick-and-dirty-carousel-11bl</guid>
      <description>&lt;p&gt;One thing I find myself looking up time and time again, is;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;How do I move the first item of an array to the end? 🤔&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So, in the spirit of &lt;em&gt;If I write it down, I'll never forget it&lt;/em&gt;, here's a quick and dirty carousel that does just that.&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;duration&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5000&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;carousel&lt;/span&gt; &lt;span class="o"&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;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;[data-carousel]&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;slides&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[...&lt;/span&gt;&lt;span class="nx"&gt;carousel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;querySelectorAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;[data-slide]&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;initCarousel&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;carousel&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;slides&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="nx"&gt;slides&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;slides&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;splice&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="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
  &lt;span class="nx"&gt;carousel&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="dl"&gt;''&lt;/span&gt;
  &lt;span class="nx"&gt;carousel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;insertAdjacentElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;afterbegin&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;slides&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="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;setInterval&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;initCarousel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;carousel&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;slides&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nx"&gt;duration&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  Let's break that down…
&lt;/h2&gt;

&lt;p&gt;First we set the duration, 5000 milliseconds (5 seconds) should be good enough.&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;duration&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5000&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, identify your elements. Your common or garden carousel consists of a container (&lt;code&gt;&amp;lt;div data-carousel /&amp;gt;&lt;/code&gt; in this case) and some slides (&lt;code&gt;&amp;lt;article data-slide /&amp;gt;&lt;/code&gt; in this case).&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;carousel&lt;/span&gt; &lt;span class="o"&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;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;[data-carousel]&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;slides&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[...&lt;/span&gt;&lt;span class="nx"&gt;carousel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;querySelectorAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;[data-slide]&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, here's where the magic happens!&lt;/p&gt;

&lt;p&gt;We have a smol function that moves the first item in the array to the end of the array then replaces the entire &lt;code&gt;innerHTML&lt;/code&gt; of the container with the first slide in the array.&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;initCarousel&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;carousel&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;slides&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="nx"&gt;slides&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;slides&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;splice&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="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
  &lt;span class="nx"&gt;carousel&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="dl"&gt;''&lt;/span&gt;
  &lt;span class="nx"&gt;carousel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;insertAdjacentElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;afterbegin&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;slides&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, we run the function over and over again, every 5 seconds…&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;setInterval&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;initCarousel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;carousel&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;slides&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nx"&gt;duration&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;And that's it!&lt;/p&gt;

&lt;p&gt;OK, sure, it doesn't have any fancy transitions but hopefully I'll remember the magic formula! 🙏&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;arr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;splice&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="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;
  &lt;span&gt;See the Pen &lt;a href="https://codepen.io/thomasxbanks/pen/xxgWQoj"&gt;
  Quick and dirty carousel&lt;/a&gt; by thomas×banks (ツ) (&lt;a href="https://codepen.io/thomasxbanks"&gt;@thomasxbanks&lt;/a&gt;)
  on &lt;a href="https://codepen.io"&gt;CodePen&lt;/a&gt;.&lt;/span&gt;
&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Increase WordPress uploads limit in Docker</title>
      <dc:creator>Thomas Rigby</dc:creator>
      <pubDate>Wed, 31 Mar 2021 00:00:00 +0000</pubDate>
      <link>https://dev.to/hryggrbyr/increase-wordpress-uploads-limit-in-docker-goh</link>
      <guid>https://dev.to/hryggrbyr/increase-wordpress-uploads-limit-in-docker-goh</guid>
      <description>&lt;p&gt;I've recently moved over to using &lt;a href="https://www.docker.com/"&gt;Docker&lt;/a&gt; to manage my WordPress builds. It has many advantages and, the more comfortable I get, relatively few disadvantages. Not sponsored or anything, it's just boss!&lt;/p&gt;

&lt;p&gt;One thing I find happens &lt;strong&gt;every single time&lt;/strong&gt; is trying to upload an image into the Media Library and getting the "filename exceeds the maximum upload size for this site" error.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--xITUFwE1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ib368419f2j382lvut14.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--xITUFwE1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ib368419f2j382lvut14.png" alt="Alt Text" width="602" height="372"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Inevitably, I find myself sticking &lt;code&gt;docker wordpress increase upload limit&lt;/code&gt; into Bing (yes, &lt;a href="https://www.bing.com/"&gt;Bing&lt;/a&gt;). There are a few answers knocking around - some of which I can get to work, some of which I can't.&lt;/p&gt;

&lt;p&gt;This is the solution that I find works for me. I'm posting it here to save myself an hour of Googling next time! 😅&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: &lt;code&gt;uploads.ini&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Firstly, create an &lt;code&gt;uploads.ini&lt;/code&gt; file in your project. I like to keep mine in a specific &lt;code&gt;config&lt;/code&gt; folder with my &lt;code&gt;.htaccess&lt;/code&gt; file.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Add your options
&lt;/h2&gt;

&lt;p&gt;In the &lt;code&gt;uploads.ini&lt;/code&gt; file, add the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;upload_max_filesize &lt;span class="o"&gt;=&lt;/span&gt; 16M
post_max_size &lt;span class="o"&gt;=&lt;/span&gt; 24M
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Feel free to change the values to suit your needs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: Include your file
&lt;/h2&gt;

&lt;p&gt;The file now needs mounting using &lt;a href="https://docs.docker.com/storage/volumes/"&gt;volumes&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you're using &lt;code&gt;docker-compose&lt;/code&gt;, it will look a little something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;3.1'&lt;/span&gt;

&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;wordpress&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;wordpress:5.7.0-php7.3-apache&lt;/span&gt;
    &lt;span class="na"&gt;restart&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;80:80&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./config/uploads.ini:/usr/local/etc/php/conf.d/uploads.ini&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./www/themes:/var/www/html/wp-content/themes:delegated&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./www/plugins:/var/www/html/wp-content/plugins:delegated&lt;/span&gt;

&lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;wordpress&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  And that's it!
&lt;/h2&gt;

&lt;p&gt;Start or restart Docker and you'll no longer get nasty errors when you try to upload that massive photo.&lt;/p&gt;

&lt;p&gt;Just be aware that upload limits exist for good reason - nobody wants to have to download a tonne of 10Mb 1920×1080 images that are only going to be used as 300px thumbnails…&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>wordpress</category>
      <category>docker</category>
    </item>
  </channel>
</rss>
