<?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: Adam Ormsby</title>
    <description>The latest articles on DEV Community by Adam Ormsby (@aormsby).</description>
    <link>https://dev.to/aormsby</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%2F169238%2F5602d94d-810a-42be-bfc4-9a4e6cc433e5.jpeg</url>
      <title>DEV Community: Adam Ormsby</title>
      <link>https://dev.to/aormsby</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/aormsby"/>
    <language>en</language>
    <item>
      <title>Refactored: Hugo Shortcodes Module</title>
      <dc:creator>Adam Ormsby</dc:creator>
      <pubDate>Wed, 08 Feb 2023 06:04:18 +0000</pubDate>
      <link>https://dev.to/aormsby/refactored-hugo-shortcodes-module-344h</link>
      <guid>https://dev.to/aormsby/refactored-hugo-shortcodes-module-344h</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;This post needed to be &lt;em&gt;Refactored&lt;/em&gt; to work on dev.to. So here's a link, a summary, and a chance to check out my personal site where I have more freedom with my format. Cheers!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I previously started an open-source project for collecting user-created Hugo shortcodes, and you can add all of them to your Hugo site as a Hugo module. I filled the starter repo with some of the shortcodes I’ve made for my own site, and I’d love for it to become a place where everybody can share theirs with everyone. Theme-agnostic shortcodes are best, of course, but I really have no guidelines for additions right now. Let’s see where it goes!&lt;/p&gt;

&lt;p&gt;Check out &lt;a href="https://www.adamormsby.com/posts/009-hugo-shortcodes-module/"&gt;my original post&lt;/a&gt; for live samples!&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--566lAguM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/aormsby"&gt;
        aormsby
      &lt;/a&gt; / &lt;a href="https://github.com/aormsby/hugo-shortcodes"&gt;
        hugo-shortcodes
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      A collection of simple Hugo shortcodes, usable as a Hugo module
    &lt;/h3&gt;
  &lt;/div&gt;
&lt;/div&gt;


</description>
      <category>hugo</category>
      <category>opensource</category>
      <category>modules</category>
    </item>
    <item>
      <title>Per-App Language Preferences in Android 13</title>
      <dc:creator>Adam Ormsby</dc:creator>
      <pubDate>Mon, 06 Feb 2023 12:00:00 +0000</pubDate>
      <link>https://dev.to/aormsby/per-app-language-preferences-in-android-13-61f</link>
      <guid>https://dev.to/aormsby/per-app-language-preferences-in-android-13-61f</guid>
      <description>&lt;p&gt;Finally, some localization updates for Android! Android 13 was released in the summer of 2022, and it has &lt;em&gt;a ton&lt;/em&gt; of cool new stuff to work with. Today, I’ll share a small piece I’m passionate about - per-app language settings.&lt;/p&gt;

&lt;p&gt;Up until now, the active locale of a device was based solely on the device’s system-wide language settings. Supporting any kind of in-app option required building custom language pickers and managing user settings in our app’s preference cache. This has been somewhat improved with per-app language settings, and I’m hoping we continue to see more support in this area. Localization can play a huge part in product acceptance and market expansion, and the less custom stuff we have to build, the less we have to maintain down the line.&lt;/p&gt;

&lt;p&gt;I had planned to write this post as more of an intro to configuring per-app language settings because I find the documentation to be a bit chaotic and hard to follow. But as I was gathering materials for that work, I found that the Android devs beat me to it! Not only have they blogged about it, but they’ve also added more info to the developer docs since the initial release - though I have to say, it’s still hard to follow with all the warnings and in-page links and… maybe just start with the blog post that I linked below.&lt;/p&gt;

&lt;p&gt;So instead of that post, what I’ll do for you instead is give a short overview of the API updates - what’s provided and what isn’t - share some sample code, and talk a bit about what I think is missing from all this.&lt;/p&gt;

&lt;h2&gt;
  
  
  Recommended Android Resources
&lt;/h2&gt;

&lt;p&gt;If you want to get more familiar with the new feature before reading on, here are the Android developer resources I recommend you look at:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://android-developers.googleblog.com/2022/11/per-app-language-preferences-part-1.html" rel="noopener noreferrer"&gt;Android Developers Blog - Per-App Language Preferences - Part 1&lt;/a&gt; - basically, the post I sat down to write!&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://developer.android.com/guide/topics/resources/app-languages" rel="noopener noreferrer"&gt;Android Docs - Per-App Language Preferences&lt;/a&gt; - messy, but good info if you’re patient&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And here are two great videos sadly buried in the docs - one an overview of the per-app setting, and one a great intro into internationalization on Android.&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/DUKnNWwcNvo"&gt;
&lt;/iframe&gt;
&lt;br&gt;
&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/Tq7TSUzAGm8"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  API Feature Overview
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What’s improved?
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Application language settings can now be system-managed
&lt;/h4&gt;

&lt;p&gt;This is big! After configuring per-app language settings, we can delegate managing a user’s language settings to Android’s system processes and stop worrying about managing language preferences ourselves. Unless you have special needs, you can throw out your custom-built system - you don’t need to maintain it anymore! Let the App Info page handle it for you.&lt;/p&gt;

&lt;p&gt;&lt;a href="img/app-language-settings.png"&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%2Flnsruzwx9tjo2c7sbzba.png" alt="Android per app language settings" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Android now provides purpose-built classes to manage active locales
&lt;/h4&gt;

&lt;p&gt;Static functions provided by the &lt;code&gt;AppCompatDelegate&lt;/code&gt; and &lt;code&gt;LocaleManagerCompat&lt;/code&gt; classes are now available to get, set, and store application locales, and between the two of them, you get access to all application- and system-level locale information you need. No more messing about with Java’s &lt;code&gt;Locale&lt;/code&gt; class and forgetting to also update your active resource configuration - keep things simple with Android’s API.&lt;/p&gt;

&lt;h4&gt;
  
  
  All of this is backward compatible
&lt;/h4&gt;

&lt;p&gt;If you use all the new classes and rely on the system to do the work, you can configure applications built for older versions of Android to also have most of the functionality of these features. Users won’t get the language selection option on your App Info page (oh well), but because you’ve configured the storage in your Manifest, you can use &lt;code&gt;AppCompatDelegate&lt;/code&gt; to set and get locale info your users may have selected through a language picker or some other method.&lt;/p&gt;

&lt;p&gt;This is particularly nice because it shows that Android is working to provide the per-app language experience to as many people as it can. I’m not sure how far back the compatibility goes, but I expect this could impact a lot of projects.&lt;/p&gt;

&lt;h3&gt;
  
  
  What’s missing?
&lt;/h3&gt;

&lt;h4&gt;
  
  
  There’s still no in-app language picker
&lt;/h4&gt;

&lt;p&gt;I sort of understand this one. Every app is different, and there’s no good way to provide a language picker that everyone will want to use. We’d probably still see a bunch of custom implementations anyway. Honestly, I’m not convinced in-app language changes are something Android ever really intended to support - at least not without jumping through hoops. Even official Android documentation pushed developers to use the system-level locale and do full restarts to reload with a new language. And the per-app settings are great, but they’re still managed at a system level. I don’t know if a language picker is on their radar. You’ll still be building your own, thank you very much.&lt;/p&gt;

&lt;p&gt;All this being said, you can absolutely navigate from your app directly to its system-managed language settings! It may not provide an ideal user experience, but the option is there. LinkedIn did it, which lines up with their track record on UX… but sometimes laziness can be good. I kind of like it.&lt;/p&gt;

&lt;p&gt;&lt;a href="img/linkedin-language-flow"&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%2Fu9x16ox844w6csmvkn5i.png" alt="LinkedIne Android per app language flow" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Configuration is pretty clean… but also there’s potentially a lot of it
&lt;/h4&gt;

&lt;p&gt;Initial configuration is not too bad - add the correct Compat libraries, create a locale XML file, update your manifest for backward compatibility, and add new API code to your app where needed. But how do you populate a language picker? None of those files generate in-app files for you to use, and I haven’t yet seen a function to retrieve all available app locales at runtime. You’ll need at least one other file for your language list, and maybe you’ll need duplicate lists to display language names for different locales. You get it all in and publish.&lt;/p&gt;

&lt;p&gt;Now, you want to add a language to your application. Good luck remember all the files you need to add it to. It may not sound like much, but it’s like updating a single string in ten places. Will you remember to update them all? And will you notice if you don’t? Again, I love this feature. I’m just not a fan of how clunky it may end up being to use.&lt;/p&gt;

&lt;p&gt;(I’ve built &lt;a href="https://github.com/aormsby/android-locale-resource-generator" rel="noopener noreferrer"&gt;a little plugin&lt;/a&gt; that may help with some aspects of this, though! More on that in my next post.)&lt;/p&gt;

&lt;h4&gt;
  
  
  This feature feels incomplete
&lt;/h4&gt;

&lt;p&gt;The documentation for the feature was crammed onto a single page, it’s filled with caveats about &lt;a href="https://developer.android.com/guide/topics/resources/app-languages#known-issues" rel="noopener noreferrer"&gt;confusing known issues&lt;/a&gt;, and there don’t seem to be any finalized, stable libraries for us to import into our projects with confidence. I mean, who wants to use the questionable &lt;code&gt;Appcompat 1.6.0-beta01&lt;/code&gt; or higher? Is it safe? Are we going to have to update when something stable arrives? No idea.&lt;/p&gt;

&lt;p&gt;Listen - I’m still excited about this feature, and you should be, too! But I’m also keeping an eye out for updates.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sample Project
&lt;/h2&gt;

&lt;p&gt;As promised, I have a sample project for you! I updated my &lt;code&gt;l10n_samples&lt;/code&gt; project with support for per-app language preferences, and I added a page with a super simple language picker. You can change the language to watch the app update in real time. Bonus - since the new locale changer updates the whole app, you no longer need to update the system language to test out the other samples. (Knew I’d get that in there eventually!)&lt;/p&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/aormsby" rel="noopener noreferrer"&gt;
        aormsby
      &lt;/a&gt; / &lt;a href="https://github.com/aormsby/android-l10n-samples" rel="noopener noreferrer"&gt;
        android-l10n-samples
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Some localization techniques for Android, read the blog posts on my site :)
    &lt;/h3&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;&lt;a href="img/locale-changer-sample.gif"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.adamormsby.com%2Fposts%2F016-android-13-localization-per-app-language-preferences%2Fimg%2Flocale-changer-sample.gif%23center" alt="Gif showing sample locale changer" width="" height=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Thanks for reading, and I hope you got something useful out of my love for internationalization. I would &lt;em&gt;love&lt;/em&gt; to answer questions and chat about this new feature, so please comment with anything you have, and we can nerd out about all this together. Happy coding!&lt;/p&gt;

</description>
      <category>android</category>
      <category>localization</category>
      <category>l10n</category>
      <category>internationalization</category>
    </item>
    <item>
      <title>WilyKit: The MacBook That Became Wall Art</title>
      <dc:creator>Adam Ormsby</dc:creator>
      <pubDate>Mon, 29 Aug 2022 12:00:00 +0000</pubDate>
      <link>https://dev.to/aormsby/wilykit-the-macbook-that-became-wall-art-3pa</link>
      <guid>https://dev.to/aormsby/wilykit-the-macbook-that-became-wall-art-3pa</guid>
      <description>&lt;p&gt;Computers get old and die just like us. Parts fail. They become obsolete. You drop them a few too many times. It happens to &lt;a href="https://i.ytimg.com/vi/j_WpEYAAmi8/maxresdefault.jpg"&gt;the best of us.&lt;/a&gt; And while there are many ways to dispose of your computer - like &lt;a href="https://www.epa.gov/recycle/electronics-donation-and-recycling"&gt;donation and recycling&lt;/a&gt; - it can sometimes feel like letting go of a friend. I felt that way about WilyKit, so I turned it into wall art. 🙂&lt;/p&gt;

&lt;p&gt;After 8 years of service, my 2013 MacBook Air finally died last year. Simple hard drive failure, &lt;a href="https://www.ifixit.com/Guide/MacBook+Air+13-Inch+Mid+2013+Solid-State+Drive+Replacement/15181"&gt;totally fixable for a hundred bucks.&lt;/a&gt; But I needed a more powerful computer to help with my work, so I just bought a new one instead.&lt;/p&gt;

&lt;p&gt;I had always planned on keeping the lid somehow, no matter how many times its dinged-up edges caught onto my bags, my clothes, and even my skin when they were feeling extra bloodthirsty. It was just so full of memories! I took that laptop around the world, wrote stories with it, learned to code on it, dropped it on its corners until it wouldn’t shut right, and stickered it full with the signposts of my youth. This was my companion, and I couldn’t just give it away.&lt;/p&gt;

&lt;p&gt;&lt;a href="//img/wilykit.jpg"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--dGHYuSCN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.adamormsby.com/posts/014-old-laptop-disassembly/img/wilykit.jpg%23center" alt="WilyKit, the worldly MacBook" width="880" height="660"&gt; &lt;/a&gt;&lt;br&gt;
&lt;em&gt;WilyKit, the worldly MacBook Air&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Finally, after a year of busyness, I performed the surgery. &lt;a href="https://www.ifixit.com/Guide/MacBook+Air+13-Inch+Mid+2013+Display+Assembly+Replacement/15407"&gt;Removing the upper display&lt;/a&gt; was quite easy, but after that I was on my own. Though most of the remaining work boiled down to peeling away the layers, the screen material can get pretty nasty when it cracks! I probably should have worn long sleeves, goggles, and a mask to be extra careful with the ’exploding’ glass particles, but it was manageable. Gloves helped a lot. What would’ve helped more is if I hadn’t cracked the glass… but it was a fun project overall.&lt;/p&gt;

&lt;p&gt;Bit by bit, I removed the bezel, many layers of screen, the hinge, and copious amounts of adhesive tape used to keep it all together… and voilà! An aluminum memory, all my own.&lt;/p&gt;

&lt;p&gt;This computer had a life. And a death. Her name was WilyKit, and she can live on my wall forever.&lt;/p&gt;

&lt;p&gt;&lt;a href="//img/display-off.jpg"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vorXCgLw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.adamormsby.com/posts/014-old-laptop-disassembly/img/display-off.jpg%23center" alt="MacBook Air disassembled" width="880" height="660"&gt; &lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="//img/layered-screen-shiny.jpg"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--trsDBFqk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.adamormsby.com/posts/014-old-laptop-disassembly/img/layered-screen-shiny.jpg%23center" alt="MacBook Air display with bezel removed" width="880" height="660"&gt; &lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="//img/layered-screen.jpg"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--oLbr_QVc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.adamormsby.com/posts/014-old-laptop-disassembly/img/layered-screen.jpg%23center" alt="MacBook Air display screen layer" width="880" height="660"&gt; &lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="//img/wilykit-final.jpg"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--4MhQgHAC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.adamormsby.com/posts/014-old-laptop-disassembly/img/wilykit-final.jpg%23center" alt="WilyKit, the MacBook Air lid turned into wall air" width="880" height="660"&gt; &lt;/a&gt;&lt;/p&gt;

</description>
      <category>hardware</category>
      <category>art</category>
      <category>fun</category>
      <category>recycling</category>
    </item>
    <item>
      <title>Localization - Formatting Dates on Android</title>
      <dc:creator>Adam Ormsby</dc:creator>
      <pubDate>Mon, 28 Mar 2022 12:00:00 +0000</pubDate>
      <link>https://dev.to/aormsby/localization-formatting-dates-on-android-2gb0</link>
      <guid>https://dev.to/aormsby/localization-formatting-dates-on-android-2gb0</guid>
      <description>&lt;p&gt;Hey everybody, let’s talk localization! It’s a passion of mine that I’d like to spend more time on, and I want to share some tips and tricks I’ve picked up in my work. Hopefully, this is only the first of many localization posts to come. Keep an eye out for more in the future!&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--566lAguM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/aormsby"&gt;
        aormsby
      &lt;/a&gt; / &lt;a href="https://github.com/aormsby/android-l10n-samples"&gt;
        android-l10n-samples
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Some localization techniques for Android, read the blog posts on my site :)
    &lt;/h3&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;Today, I want to look at &lt;em&gt;&lt;strong&gt;date formatting&lt;/strong&gt;&lt;/em&gt; for Android applications. When you want to display a date in your app, you have to keep in mind that your customers in different locales will expect dates to look the way they’re used to seeing them. But while there are a lot of date formatting options on Android, they aren’t all robust enough to ‘just work’ the way you need them to.&lt;/p&gt;

&lt;p&gt;So first, let’s take a look at two common solutions that aren’t as great as they seem. Then I’ll show you a how to get you exactly the format you want every time.&lt;/p&gt;

&lt;h2&gt;
  
  
  LocalDate, LocalTime, LocalDateTime - from java.time
&lt;/h2&gt;

&lt;p&gt;These newer Java 8 time classes were built to take the place of the old, clunky &lt;a href="https://docs.oracle.com/javase/8/docs/api/java/util/Date.html"&gt;Date&lt;/a&gt;, &lt;a href="https://docs.oracle.com/javase/7/docs/api/java/util/Calendar.html"&gt;Calendar&lt;/a&gt;, and &lt;a href="https://docs.oracle.com/javase/7/docs/api/java/text/DateFormat.html"&gt;DateFormat&lt;/a&gt; classes - which you should &lt;em&gt;never&lt;/em&gt; rely on completely for localized dates because they’re junk. But this new &lt;em&gt;java.time&lt;/em&gt; library is supposed to take care of all the problems developers had with the old ones. So… problem solved?&lt;/p&gt;

&lt;p&gt;Maybe for Java devs, but this newer library only works with &lt;em&gt;API 26 or higher&lt;/em&gt; on Android. Many projects still support older APIs, so these libraries simply aren’t an option them. However, if you don’t have to worry about that, give these a shot! I’ll see if I can spend some time with these in the future and share my thoughts.&lt;/p&gt;

&lt;h2&gt;
  
  
  SimpleDateFormat - from java.text
&lt;/h2&gt;

&lt;p&gt;A &lt;em&gt;ton&lt;/em&gt; of Android projects take advantage of &lt;a href="https://developer.android.com/reference/java/text/SimpleDateFormat"&gt;SimpleDateFormat&lt;/a&gt;, and why wouldn’t you? Even the Android docs say this class is &lt;code&gt;for formatting and parsing dates in a locale-sensitive manner&lt;/code&gt;. Sounds great, right? Well, I think it’s a bit of a trap.&lt;/p&gt;

&lt;p&gt;Java’s SimpleDateFormat is a really attractive solution for anyone who previously tried the DateFormat class and found the formatting options to be really restrictive. DateFormat supports a limited number of &lt;em&gt;pre-determined&lt;/em&gt; date-time arrangements, and plenty of desirable options are missing - like showing the month and date without the year. (The year is &lt;em&gt;always there&lt;/em&gt;! Augh!! Hair pulling madness.) But with SimpleDateFormat, you can use a string value to explicitly build your own date format.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;val myFormat = SimpleDateFormat("MMMM dd, yyyy")
// no locale specified, uses Locale.getDefault()

val date = Date()
println(myFormat.parse(date))

/* sample output
en_US, USA -- December 07, 2008
fr_FR, France -- décembre 07, 2008
*/

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

&lt;/div&gt;



&lt;p&gt;Super easy, right? Well, if you have keen eyes and you’re familiar with the date format in France, you’ve already noticed the sample output would be incorrect for that region. France puts the day number before the month!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;wrong -&amp;gt; décembre 07, 2008
right -&amp;gt; 07 décembre 2008

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;And that’s the trap.&lt;/strong&gt; The main reason to use SimpleDateFormat is to create your own format, but when you create your own format, it’s not really ‘locale-sensitive’ after all! And that’s a bit of a contradiction, I think.&lt;/p&gt;

&lt;p&gt;In the end, your hard-coded string is the problem, and no matter what locale your app is running in, that format never changes to match. Now, there’s a way around this - you can extract your format string into a &lt;code&gt;strings.xml&lt;/code&gt; resource file and add a ‘translated’ version of the format in the French resource.&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;!-- res/values-en/strings.xml --&amp;gt;
&amp;lt;string name="date_format_1"&amp;gt;MMMM dd, yyyy&amp;lt;/string&amp;gt;

&amp;lt;!-- res/values-fr/strings.xml --&amp;gt;
&amp;lt;string name="date_format_1"&amp;gt;dd MMMM yyyy&amp;lt;/string&amp;gt;

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

&lt;/div&gt;



&lt;p&gt;This works fine, and it might seem reasonable at first. But if your project needs 10 different date formats in 10 different languages… that’s already 100 formatting strings you need to add to your resources and keep track of over time.&lt;/p&gt;

&lt;p&gt;If you need that kind of specificity, give it a shot! But I don’t think you do, and I’m about to prove it. Let’s take a look a look at DateUtils - the tool that does all this junk for you.&lt;/p&gt;

&lt;h2&gt;
  
  
  DateUtils
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://developer.android.com/reference/android/text/format/DateUtils"&gt;DateUtils&lt;/a&gt; is the absolute &lt;em&gt;bomb&lt;/em&gt; for date formatting on Android. It’s flexible, robust, and aboslutely &lt;em&gt;is&lt;/em&gt; sensitive to your customer’s active locale. In fact, you’re not even allowed to specify the locale being used when you format with DateUtils, and for the large majority of common date formatting needs, this is absolutely what you want. You want the system to handle most things for you, and DateUtils does this well.&lt;/p&gt;

&lt;p&gt;The flexibility in using DateUtils comes from its bitmask formatting flags. They allow you to specify &lt;em&gt;exactly&lt;/em&gt; which date or time components you want to appear in your formatted date value, but instead of showing up in the order you choose (like with the string from before), they act as simple on/off switches independent of order or locale. Here’s an example.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;println(
  DateUtils.formatDateTime(
    context, // needs a Context
    myDate, // the Date object to format
    DateUtils.FORMAT_SHOW_DATE // the format flag for showind 'date' (includes year)
  )
}

/* output:
en_US -&amp;gt; September 25, 2005
fr_FR -&amp;gt; 25 septembre 2005
zh_CN -&amp;gt; 2005年9月25日
*/

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

&lt;/div&gt;



&lt;p&gt;Let’s break this down a bit:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;DateUtils.formatDateTime&lt;/code&gt; outputs a &lt;code&gt;String&lt;/code&gt; value&lt;/li&gt;
&lt;li&gt;First param is a &lt;code&gt;Context&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Second param is the &lt;code&gt;Date&lt;/code&gt; you want to format&lt;/li&gt;
&lt;li&gt;Third param is the set of format flags you want to apply to the Date&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And that’s it! No explicit format strings, no translated format resources, no locale problems! It &lt;em&gt;just works.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Let’s see how you can use the bit flags to remove the year now.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;DateUtils.FORMAT_SHOW_DATE or DateUtils.FORMAT_NO_YEAR

/* output:
en_US -&amp;gt; September 25
fr_FR -&amp;gt; 25 septembre
zh_CN -&amp;gt; 9月25日
*/

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

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;or&lt;/code&gt; bit operator takes both of the flags, combines them, and outputs a format with both flags enabled. This works with &lt;em&gt;any&lt;/em&gt; number of formatting flags, including things like word abbreviations, numeric dates, showing weekdays, showing time, hiding the month, etc. Here are &lt;a href="https://developer.android.com/reference/android/text/format/DateUtils#constants_1"&gt;all the available flags&lt;/a&gt; for you.&lt;/p&gt;

&lt;p&gt;DateUtils is truly the most flexible, easy-to-use, &lt;em&gt;built-in&lt;/em&gt; date formatter I’ve come across for Android projects. If you aren’t using it yet, you should &lt;em&gt;really&lt;/em&gt; think about switching to it today.&lt;/p&gt;

&lt;h2&gt;
  
  
  DateUtils and Kotlin Extension Functions
&lt;/h2&gt;

&lt;p&gt;Want to supercharge your use of DateUtils? Use it in some Kotlin extension functions! Here are some fantastic samples from the Github project linked at the top of this post. These are ready for use in your project today!&lt;/p&gt;

&lt;p&gt;Show only the time:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;fun Date.asTime(context: Context): String =
    DateUtils.formatDateTime(context, time, DateUtils.FORMAT_SHOW_TIME)

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

&lt;/div&gt;



&lt;p&gt;Show date with year, numeric and abbreviation options:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;fun Date.asDateWithYear(
    context: Context,
    numeric: Boolean = false,
    abbreviated: Boolean = false
): String {
    var formatFlags = DateUtils.FORMAT_SHOW_DATE
    if (numeric) formatFlags = formatFlags or DateUtils.FORMAT_NUMERIC_DATE
    if (abbreviated) formatFlags = formatFlags or DateUtils.FORMAT_ABBREV_MONTH

    return DateUtils.formatDateTime(context, time, formatFlags)
}

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

&lt;/div&gt;



&lt;p&gt;Dynamically show the time (if date is today) or the date (if date is not today):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;fun Date.asTimeOrRecentDate(): String =
    DateUtils.formatSameDayTime(
        time,
        Date().time,
        DateFormat.LONG,
        DateFormat.SHORT
    ).toString()

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

&lt;/div&gt;



&lt;p&gt;And something &lt;em&gt;super&lt;/em&gt; flexible!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;fun Date.flexFormatted(
    context: Context,
    showWeekday: Boolean = false,
    showMonth: Boolean = true,
    showMonthDay: Boolean = true,
    showYear: Boolean = false,
    showTime: Boolean = false,
    numeric: Boolean = false,
    abbreviated: Boolean = false,
): String {
    var formatFlags = 0 // starts blank
    if (showWeekday) formatFlags = formatFlags or DateUtils.FORMAT_SHOW_WEEKDAY
    if (showMonth) formatFlags = formatFlags or DateUtils.FORMAT_SHOW_DATE
    if (!showMonthDay) formatFlags = formatFlags or DateUtils.FORMAT_NO_MONTH_DAY
    if (!showYear) formatFlags = formatFlags or DateUtils.FORMAT_NO_YEAR
    if (showTime) formatFlags = formatFlags or DateUtils.FORMAT_SHOW_TIME
    if (numeric) formatFlags = formatFlags or DateUtils.FORMAT_NUMERIC_DATE
    if (abbreviated) formatFlags = formatFlags or DateUtils.FORMAT_ABBREV_MONTH or DateUtils.FORMAT_ABBREV_WEEKDAY

    return DateUtils.formatDateTime(context, time, formatFlags)
}

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

&lt;/div&gt;






&lt;p&gt;Thanks for reading! I hope this little trip into the world of localization was as fun for you as it was for me. Please - ask questions, give opinions, and share your ideas in the comments! I’d love to swap date formatting stories with you. Cheers!&lt;/p&gt;

</description>
      <category>android</category>
      <category>localization</category>
      <category>l10n</category>
      <category>internationalization</category>
    </item>
    <item>
      <title>Using Hugo Modules Instead of Git Submodules</title>
      <dc:creator>Adam Ormsby</dc:creator>
      <pubDate>Mon, 13 Dec 2021 06:00:00 +0000</pubDate>
      <link>https://dev.to/aormsby/using-hugo-modules-instead-of-git-submodules-1dbl</link>
      <guid>https://dev.to/aormsby/using-hugo-modules-instead-of-git-submodules-1dbl</guid>
      <description>&lt;p&gt;Hey there, folks! I know I’m a little late to this party, but it’s time I talked about working with Hugo Modules. A while ago I wrote a post on building a Hugo site with Git submodules (see the series links above!), but let’s be honest - that’s a lot of work.&lt;/p&gt;

&lt;p&gt;Setting up git submodules and managing them over time can be a headache, especially for larger projects, and that kind of configuration just brings in a lot of overhead you may not want to deal with long term. For a more manageable project, I now recommend Hugo modules.&lt;/p&gt;

&lt;h2&gt;
  
  
  Benefits of Hugo Modules
&lt;/h2&gt;

&lt;p&gt;The Hugo module system is powered by Go modules, which I don’t really know anything about. Feel free to explore that on your own. What I do know is this –&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Hugo modules are:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;quick to configure&lt;/li&gt;
&lt;li&gt;less work to implement in your project repo&lt;/li&gt;
&lt;li&gt;great for customizing your site’s look without needing to fork a full theme&lt;/li&gt;
&lt;li&gt;an awesome way to share open-source code for Hugo&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;No more managing git submodules. No more using complex commit/push/pull schemes to work with your site repository. No more confusion about how to modify and build somebody’s theme to fit your specific project needs. Everything you were using git submodules for can (and probably should) be converted to using Hugo modules.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to Configure a Hugo Module
&lt;/h2&gt;

&lt;p&gt;If all you want is to include a module in your project, setup is super simple. In your project configuration file (&lt;code&gt;config.toml&lt;/code&gt; or yaml or whatever), add the path to the module you want to import. For online resources, add a full URL. For local resources, add a filepath.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[module]
  [[module.imports]]
    path = "github.com/aormsby/hugo-shortcodes"
  [[module.imports]]
    path = "github.com/aormsby/hugo-custom-layouts"
  [[module.imports]]
    path = "github.com/aormsby/papermod-custom"
  [[module.imports]]
    path = "github.com/adityatelange/hugo-PaperMod"

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

&lt;/div&gt;



&lt;p&gt;A few things to take note of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;This example is toml. Yaml has different syntax.&lt;/li&gt;
&lt;li&gt;This is just configuration. You still need to initialize Hugo modules. (More on that shortly.)&lt;/li&gt;
&lt;li&gt;The order of your modules is important!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Modules on the bottom will get loaded first, so keep anything you don’t want overridden higher up in the module chain. All conflicting files during module import will use the &lt;em&gt;last file loaded&lt;/em&gt;. If you want to override anything from a module you can use this bottom-to-top loading to your advantage. I show an example of this later on.&lt;/p&gt;

&lt;p&gt;Next, you have to tell your project that you want to import these modules on build and how to import them. In your terminal, run the following commands in order –&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt; hugo mod init github.com/&amp;lt;your_username&amp;gt;/&amp;lt;your_project&amp;gt;
# initializes the hugo module system in your project (I used my repo URL here, any string seems fine)

&amp;gt; hugo mod get
# gets a reference to the latest version of each module, stored in 'go.mod'

&amp;gt; hugo mod vendor
# optional, downloads a local copy of the modules

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

&lt;/div&gt;



&lt;p&gt;Now when you build your site, the Hugo module system pulls data from all of the paths in your configuration file and makes a build with all of the data from the included modules. This could be extra layouts, assets, i18n data, shortcodes, etc., and it’s all included in your site without a whole bunch of extra setup.&lt;/p&gt;

&lt;p&gt;Keep in mind that the stored module references in &lt;code&gt;go.mod&lt;/code&gt; are references to a specific commit on a github repo, not a branch. You should be able to configure these by modifying the references (or perhaps there’s a command for it I don’t know), but maybe think before you do. If you point to a branch head, for example, every build could pull in new changes you haven’t vetted for your site. Sticking with a specific commit hash is probably better here.&lt;/p&gt;

&lt;p&gt;You can run &lt;code&gt;hugo mod get -u&lt;/code&gt; to update references to all of your modules, but keep in mind this does not update the local ‘vendor’ copies. You have to run &lt;code&gt;hugo mod vendor&lt;/code&gt; again for that.&lt;/p&gt;

&lt;p&gt;A note on &lt;code&gt;hugo mod vendor&lt;/code&gt; - So far I’ve seen two benefits of downloading local copies of your modules.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;You can see all of the assets you’re building from local module folders and modify them as you wish. I’ve found it nice to play around with theme settings and then save the changes in my own modules to override them. Vendorizing creates a code playground for you in this way.&lt;/li&gt;
&lt;li&gt;If you ever want to save a specific module configuration as part of a git commit, vendorizing allows you to include the modules at the state they’re in when you last confirmed a good build. It’s handy.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;There’s a lot more you can configure with Hugo modules, but I never needed more than this for a simple site like mine. If you want to explore your options, I encourage you to check out &lt;a href="https://gohugo.io/hugo-modules/"&gt;Hugo’s module docs&lt;/a&gt; for more information.&lt;/p&gt;

&lt;h2&gt;
  
  
  How Modules Can Help You
&lt;/h2&gt;

&lt;p&gt;As you saw before, I have four different modules I import for this site. Each has a different use case that has helped me organize my site and my assets better, and I want to share them here to give you some ideas on how you can take advantage of modules, too.&lt;/p&gt;

&lt;h3&gt;
  
  
  Basic Theme Customizations
&lt;/h3&gt;

&lt;p&gt;I’m currently using the Paper Mod theme as the core of my layouts, but I wanted to customize a few pieces. If I was using git submodules like I used to, making customizations would have required forking the theme setting up a branch for my changes and referencing my entire theme fork as a submodule. But that’s overkill for a few small changes.&lt;/p&gt;

&lt;p&gt;Instead of that, I created my own module called &lt;code&gt;papermod-custom&lt;/code&gt; where I have a few custom layout files… and nothing else. Seriously, my module only has 4 files. This works because of the bottom-to-top module imports we talked about earlier. First, I import the core theme module that contains the base theme. Then my customizations are imported, and &lt;em&gt;since I named my layouts the same as in the core theme module&lt;/em&gt;, any conflicting files are overridden with my customizations.&lt;/p&gt;

&lt;p&gt;Boom. Customized theme with little to no effort.&lt;/p&gt;

&lt;p&gt;My &lt;code&gt;papermod-custom&lt;/code&gt; file hierarchy –&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;papermod-custom #root
 |-assets
   |-css
     |-extended
       |-userCustom.css # new file, additional styling
 |-layouts
   |-_default
     |-project-list.html # new file, additional layout
   |-partials
     |-home_info.html # name conflict, overrides core theme file
     |-social_icons.html # name conflict, overrides core theme file

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  Common Site Code
&lt;/h3&gt;

&lt;p&gt;Let’s say you have 10 Hugo sites that you’re managing, and you have the same layout file in each of them. It’s an awesome layout file - why wouldn’t you reuse it? Well, instead of updating it 10 times whenever you feel it needs a change, you can save it in your own Hugo module that you import into all of those projects.&lt;/p&gt;

&lt;p&gt;Perfect example - I like &lt;a href="https://adamormsby.com/404"&gt;my 404 page&lt;/a&gt;, and I always want to enable disqus comments. I can put those two layout files into my &lt;code&gt;hugo-custom-layouts&lt;/code&gt; module and import them wherever I want. Modules make it easy to share things.&lt;/p&gt;

&lt;h3&gt;
  
  
  Additional Elements
&lt;/h3&gt;

&lt;p&gt;I like shortcodes, and I want to add someone’s public shortcodes to my site. If I start a collection of shortcodes and make it a Hugo module - &lt;a href="https://github.com/aormsby/hugo-shortcodes"&gt;like so&lt;/a&gt; - I can add them to any project with a quick module import. It’s not just true of shortcodes, of course. Any kind of Hugo-supported asset can be thrown into a module for a quick addition to your project.&lt;/p&gt;

&lt;p&gt;I hope this shows you that Hugo modules are pretty fantastic to work with and how much nicer they are than git submodules. If I’d known that a year ago, maybe I never would have written about git submodules! No matter. We’re here now, and that’s what counts! Happy coding!&lt;/p&gt;

</description>
      <category>hugo</category>
      <category>jamstack</category>
      <category>submodules</category>
      <category>modules</category>
    </item>
    <item>
      <title>Github Action: Fork Sync With Upstream</title>
      <dc:creator>Adam Ormsby</dc:creator>
      <pubDate>Sat, 10 Oct 2020 10:00:00 +0000</pubDate>
      <link>https://dev.to/aormsby/github-action-fork-sync-with-upstream-54p7</link>
      <guid>https://dev.to/aormsby/github-action-fork-sync-with-upstream-54p7</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--rr6thUED--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.adamormsby.com/posts/github-projects/actions/fork-sync-with-upstream/cover.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--rr6thUED--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.adamormsby.com/posts/github-projects/actions/fork-sync-with-upstream/cover.png" alt="" width="700" height="150"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  On github:
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://github.com/aormsby/Fork-Sync-With-Upstream-action"&gt;View action on Github&lt;/a&gt;&lt;br&gt;
&lt;a href="https://github.com/aormsby"&gt;Follow @aormsby on Github&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;These days, automation is key to saving time and minimizing errors. But if you’ve never worked with automation, it’s good to start small. This was exactly my thought when I made my first Github Action. It’s available now on the Github Marketplace if you want to try it out - &lt;a href="https://github.com/marketplace/actions/fork-sync-with-upstream"&gt;Fork Sync With Upstream&lt;/a&gt;. Let’s see what it does!&lt;/p&gt;
&lt;h2&gt;
  
  
  How It Works
&lt;/h2&gt;

&lt;p&gt;Remember my post on &lt;a href="https://dev.to/aormsby/hugo-themes-making-modifications-while-keeping-the-source-up-to-date-490g-temp-slug-6467488"&gt;making modifications to a Hugo theme&lt;/a&gt;? We forked a theme repository and saw how to make custom modifications to our local version of it. Whenever we wanted to pull updates from the source repo, we ran a bunch of git commands to pull new commits from the upstream repo and then push them to our fork. Syncing with commands like that is all well and good, but let’s save ourselves a little time by automating that process.&lt;/p&gt;

&lt;p&gt;The Fork Sync With Upstream action takes care of all those updates for us without any work on our part. At its core, the action is a shell script that runs on a Github server and automatically does the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Checkout your fork (needed for the sync process)&lt;/li&gt;
&lt;li&gt;Set the upstream repo to pull updates from&lt;/li&gt;
&lt;li&gt;Check if there are any new commits to sync (and print the commit information)&lt;/li&gt;
&lt;li&gt;Pull from the upstream repo&lt;/li&gt;
&lt;li&gt;Push to the target branch of the target repo&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Just add my action to a Github workflow file in your repo, and &lt;em&gt;voila!&lt;/em&gt; All that update work you were doing manually is now automated!&lt;/p&gt;
&lt;h2&gt;
  
  
  Running the Fork Sync
&lt;/h2&gt;

&lt;p&gt;If you’ve never made a Github workflow before, it’s a little bit confusing to figure out at first. (At least, it all was for me.) I recommend reading some of the &lt;a href="https://docs.github.com/en/actions"&gt;Github Actions documentation&lt;/a&gt; to get a better feel for how all the pieces work together.&lt;/p&gt;

&lt;p&gt;For those looking for a quick sample workflow, here’s the one I’m using in &lt;a href="https://github.com/aormsby/F-hugo-theme-hello-friend"&gt;my fork of Hello Friend&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;on:
  schedule:
    - cron: '0 7 * * 1,4'
    # scheduled at 07:00 every Monday and Thursday

jobs:
  sync_with_upstream:
    runs-on: ubuntu-latest
    name: Sync master with upstream latest

    steps:
    - name: Checkout master
      uses: actions/checkout@v2
      with:
        ref: master

    - name: Pull upstream changes
      id: sync
      uses: aormsby/Fork-Sync-With-Upstream-action@v1
      with:
        upstream_repository: panr/hugo-theme-hello-friend
        upstream_branch: master

    - name: Timestamp
      run: date

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

&lt;/div&gt;



&lt;p&gt;(Actual file at &lt;a href="https://github.com/aormsby/F-hugo-theme-hello-friend/blob/Working/.github/workflows/wf-fork-sync.yaml"&gt;.github/workflows/wf-fork-sync.yaml&lt;/a&gt;.)&lt;/p&gt;

&lt;p&gt;This may not be the only Action built for syncing with a remote, but it certainly has a better README than many of the other ones I’ve seen! For more details on using input variables and options, visit the official Marketplace page for &lt;a href="https://github.com/marketplace/actions/fork-sync-with-upstream"&gt;Fork Sync With Upstream&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Behind The Scenes
&lt;/h2&gt;

&lt;p&gt;Just some extra dev notes if you’re interested. 🙂&lt;/p&gt;

&lt;p&gt;Github Actions currently have to be created as Docker container actions or JavaScript actions. I went with JavaScript because it’s more familiar to me, and I don’t need to run this action in any specific Docker-simulated environment.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;action.yaml&lt;/code&gt; file declares all the input variables needed for the action and then runs &lt;code&gt;main.js&lt;/code&gt;. At the moment, &lt;code&gt;main.js&lt;/code&gt; exists only to run the shell script &lt;code&gt;upstream-sync.sh&lt;/code&gt;, which is where the sync really happens. This could change in the future.&lt;/p&gt;

&lt;p&gt;I used both &lt;code&gt;@actions/core&lt;/code&gt; and &lt;code&gt;@actions/exec&lt;/code&gt; from the &lt;a href="https://github.com/actions/toolkit"&gt;Github Actions Toolkit&lt;/a&gt; to simplify the functionality in &lt;code&gt;main.js&lt;/code&gt;. The shell script is called by &lt;code&gt;exec&lt;/code&gt;, which I think of as an ‘easy’ version of the &lt;code&gt;exec&lt;/code&gt; function in node.js. Some of the actions and tools that Github has made are really quite useful.&lt;/p&gt;

&lt;p&gt;Anyway, try it out! Let me know how you like it. I’m also planning on turning my &lt;a href="https://dev.to/aormsby/build-and-deploy-a-shell-script-for-hugo-sites-l99-temp-slug-3554291"&gt;shell deploy script&lt;/a&gt; into an action, so be on the lookout for that. And if you like my work, please consider buying me a coffee. Cheers!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.buymeacoffee.com/aormsby"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--TtGiCgSp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.buymeacoffee.com/buttons/default-green.png" alt="Buy Me A Coffee" width="434" height="100"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/aormsby/Fork-Sync-With-Upstream-action"&gt;View action on Github&lt;/a&gt;&lt;br&gt;
&lt;a href="https://github.com/aormsby"&gt;Follow @aormsby on Github&lt;/a&gt;&lt;/p&gt;

</description>
      <category>github</category>
      <category>githubactions</category>
      <category>automation</category>
      <category>ci</category>
    </item>
    <item>
      <title>How to Set Up a Hugo Site on Github Pages - with Git Submodules!</title>
      <dc:creator>Adam Ormsby</dc:creator>
      <pubDate>Tue, 29 Sep 2020 22:00:00 +0000</pubDate>
      <link>https://dev.to/aormsby/how-to-set-up-a-hugo-site-on-github-pages-with-git-submodules-106p</link>
      <guid>https://dev.to/aormsby/how-to-set-up-a-hugo-site-on-github-pages-with-git-submodules-106p</guid>
      <description>&lt;h2&gt;
  
  
  Overview
&lt;/h2&gt;

&lt;p&gt;I made this blog site using the &lt;a href="https://www.gohugo.io" rel="noopener noreferrer"&gt;Hugo static site generator&lt;/a&gt; because I wanted to build a simple site where I could have full control over every detail - &lt;em&gt;not&lt;/em&gt; like using Wordpress, Squarespace, or Wix. With Hugo, I can add and remove templates and functionality at will, and it feels &lt;em&gt;great&lt;/em&gt; to have that kind of power. You probably ended up here because you want that, too.&lt;/p&gt;

&lt;p&gt;In this post, we’ll take a look at how to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create a new Hugo site&lt;/li&gt;
&lt;li&gt;Host it on Github Pages&lt;/li&gt;
&lt;li&gt;Use git submodules to separate our site’s key directories into manageable chunks&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We’ll also go over the benefits (and drawbacks) of using submodules in our setup, and by the end of this post, we’ll have a new Hugo project hosted on Github Pages and ready for action.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Please note: I’ll talk a little about branching inside our submodules in the next post. To keep things simple, you can assume that I’ve stayed on the main ‘master’ branch of each git module. Also, I work on a Mac so all of my commands are Mac-specific.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Git Submodules?
&lt;/h3&gt;

&lt;p&gt;Every git project is stored as a versioned code repository (a repo). Git submodules allow us to reference other repos within a project, which effectively puts a project inside a project (or a repo inside a repo). The submodule’s code can then be used by the main project, but the submodule &lt;em&gt;&lt;strong&gt;maintains its own commit and branch history,&lt;/strong&gt;&lt;/em&gt; which separates the projects and can be a pretty powerful thing.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.adamormsby.com%2Fposts%2Fhow-to-set-up-a-hugo-site-on-github-pages-with-submodules%2Fimg%2Fexplain-submodules.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.adamormsby.com%2Fposts%2Fhow-to-set-up-a-hugo-site-on-github-pages-with-submodules%2Fimg%2Fexplain-submodules.jpg" alt="diagram showing how code is included using submodules with a git project"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In a Hugo project, most of what we see is source data - the raw files we manipulate before building our site. After Hugo builds our site, our ‘ready-to-publish’ data gets output to the &lt;code&gt;public&lt;/code&gt; directory of our project. By turning the &lt;code&gt;public&lt;/code&gt; folder into a submodule of the main project, we can treat it as a separate entity with a separate history. Let’s see what that process looks like.&lt;/p&gt;

&lt;h2&gt;
  
  
  Install Hugo and Create a Project
&lt;/h2&gt;

&lt;p&gt;First things first, we need to install Hugo! We’ll run through the key Mac commands quickly here, but if you need any more help you can always check &lt;a href="https://gohugo.io/getting-started/quick-start/" rel="noopener noreferrer"&gt;Hugo’s ‘Quick Start’ guide&lt;/a&gt; for more details or information about installing on Windows and Linux.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# 1. Open a terminal. Alternatively, you can VSCode's terminal - it's great!

# 2. If you don't have brew installed --
&amp;gt; /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)"

# 3. Install Hugo
&amp;gt; brew install hugo

# 4. Move to the directory where you want to create the project.
&amp;gt; cd [MY/DIRECTORY/NAME]

# 5. Create a new Hugo project. I'll use "hugo-gh" as my sample name.
&amp;gt; hugo new site [SITE_NAME]

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

&lt;/div&gt;



&lt;p&gt;So far, we’ve installed Hugo on our machine and created a new template project named &lt;strong&gt;hugo-gh&lt;/strong&gt;. If you’re following Hugo’s Quick Start guide, you may be tempted to move straight on to adding a theme, running the local server, and seeing your site. We’ll &lt;em&gt;absolutely&lt;/em&gt; get to all that, but since our goal here is to use git submodules to manage the different parts of our project, it would benefit us to go through some setup steps on Github first.&lt;/p&gt;

&lt;h2&gt;
  
  
  Push Project Files to Github
&lt;/h2&gt;

&lt;p&gt;Let’s get our project versioned with Github right away! We’ll need to create two repositories on Github - one to host our source code and one to host our live site data.&lt;/p&gt;

&lt;h3&gt;
  
  
  Source Code Repository
&lt;/h3&gt;

&lt;p&gt;Sign in to Github and create a new repository. I’ll call mine &lt;strong&gt;hugo-gh-pages-source&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.adamormsby.com%2Fposts%2Fhow-to-set-up-a-hugo-site-on-github-pages-with-submodules%2Fimg%2Fgithub-new-repo.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.adamormsby.com%2Fposts%2Fhow-to-set-up-a-hugo-site-on-github-pages-with-submodules%2Fimg%2Fgithub-new-repo.jpg" alt="create a new github repo"&gt;&lt;/a&gt; &lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.adamormsby.com%2Fposts%2Fhow-to-set-up-a-hugo-site-on-github-pages-with-submodules%2Fimg%2Fgithub-repo-name.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.adamormsby.com%2Fposts%2Fhow-to-set-up-a-hugo-site-on-github-pages-with-submodules%2Fimg%2Fgithub-repo-name.jpg" alt="name the new github repo"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;Hot tip:&lt;/strong&gt; If we create a repo without a README file it’s easier to avoid accidental history conflicts when pushing a local project to a fresh repo. We can always add one later.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;When our new empty repo is ready, go back to the terminal window and input these commands to initialize our local repo and push to Github.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;(If you already have a &lt;code&gt;public&lt;/code&gt; folder in your project, delete it before doing any of this to save some headaches.)&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# 1. Enter the project folder.
&amp;gt; cd hugo-gh

# 2. Initialize git locally.
&amp;gt; git init

# 3. Set our new Github repo as the remote for our local project
# (my sample URL - https://github.com/aormsby/hugo-gh-pages-source.git)
&amp;gt; git remote add origin https://github.com/[GITHUB_USERNAME]/[SOURCE_REPO_NAME].git

# 4. Stage all files for commit.
&amp;gt; git add .

# 5. Commit files.
&amp;gt; git commit -m "committing our hugo template"

# 6. Push to the remote master
&amp;gt; git push -u origin master

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

&lt;/div&gt;



&lt;p&gt;And there you have it! Our project source is now pushed to our Github repo.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.adamormsby.com%2Fposts%2Fhow-to-set-up-a-hugo-site-on-github-pages-with-submodules%2Fimg%2Fsource-pushed.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.adamormsby.com%2Fposts%2Fhow-to-set-up-a-hugo-site-on-github-pages-with-submodules%2Fimg%2Fsource-pushed.jpg" alt="source project pushed to Github"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You could &lt;em&gt;absolutely&lt;/em&gt; set up your source repo to be the host of your site using Github Pages, and you may have good reasons for doing so. That would require a different setup that you can find steps for on Hugo’s &lt;a href="https://gohugo.io/hosting-and-deployment/hosting-on-github/#deployment-of-project-pages-from-docs-folder-on-master-branch" rel="noopener noreferrer"&gt;Host on Github&lt;/a&gt; docs page. However, if we do this we ignore our chance to separate &lt;code&gt;public&lt;/code&gt; into a separately versioned repo. To accomplish this, we have to create a second repository.&lt;/p&gt;

&lt;h3&gt;
  
  
  Live Site Data Repository
&lt;/h3&gt;

&lt;p&gt;Let’s add our first submodule to the project! Remember, our goal is to separate the commit histories of our project source and our site build output to the &lt;code&gt;public&lt;/code&gt; directory. First, we create another repo on Github for our public site data. I’ll call mine &lt;strong&gt;hugo-gh-pages-public&lt;/strong&gt;. In our local terminal, run the following command from the project root.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# my sample URL - https://github.com/aormsby/hugo-gh-pages-public.git
&amp;gt; git submodule add https://github.com/[GITHUB_USERNAME]/[PUBLIC_REPO_NAME].git public

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

&lt;/div&gt;



&lt;p&gt;Sweet! We now have a submodule initialized and loaded into our project under the &lt;code&gt;public&lt;/code&gt; directory, and it’s already connected to its remote origin. Let’s do a quick site build just to put something into the remote Github repo. The commands needed are a little tedious, but it’s good to know the process.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# 1. Perform a site build and output to 'public/' directory.
&amp;gt; hugo

# 2-4.
&amp;gt; cd public
&amp;gt; git add .
&amp;gt; git commit -m "first build"

# 5. Return to the project root.
&amp;gt; cd ../

# 6-7.
&amp;gt; git add .
&amp;gt; git commit -m "first build - update submodule reference"

# 8. Push the source project *and* the public submodule to Github together.
&amp;gt; git push -u origin master --recurse-submodules=on-demand

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

&lt;/div&gt;



&lt;p&gt;It’s &lt;em&gt;&lt;strong&gt;super important&lt;/strong&gt;&lt;/em&gt; when we build to make sure that we commit and push &lt;em&gt;both&lt;/em&gt; the public submodule and the main project. For each submodule commit, the project updates its reference to the submodule to maintain its connection to the correct commit. The &lt;code&gt;--recurse-submodules=on-demand&lt;/code&gt; command pushes all of the project modules at the same time.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.adamormsby.com%2Fposts%2Fhow-to-set-up-a-hugo-site-on-github-pages-with-submodules%2Fimg%2Fsubmodule-reference-terminal.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.adamormsby.com%2Fposts%2Fhow-to-set-up-a-hugo-site-on-github-pages-with-submodules%2Fimg%2Fsubmodule-reference-terminal.jpg" alt="submodule reference in terminal using git status command"&gt;&lt;/a&gt;submodule reference updated vied in the terminal after &lt;code&gt;git status&lt;/code&gt; command&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.adamormsby.com%2Fposts%2Fhow-to-set-up-a-hugo-site-on-github-pages-with-submodules%2Fimg%2Fsubmodule-reference-github.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.adamormsby.com%2Fposts%2Fhow-to-set-up-a-hugo-site-on-github-pages-with-submodules%2Fimg%2Fsubmodule-reference-github.jpg" alt="submodule reference on github after pushing"&gt;&lt;/a&gt;submodule reference on github after pushing&lt;/p&gt;

&lt;h2&gt;
  
  
  Enable Github Pages
&lt;/h2&gt;

&lt;p&gt;On Github, our &lt;strong&gt;hugo-gh-pages-public&lt;/strong&gt; repo now has some data. Go to the repo settings and find the Github Pages section. Set the &lt;strong&gt;Source&lt;/strong&gt; of our site to &lt;strong&gt;master branch&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.adamormsby.com%2Fposts%2Fhow-to-set-up-a-hugo-site-on-github-pages-with-submodules%2Fimg%2Fgithub-pages-settings.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.adamormsby.com%2Fposts%2Fhow-to-set-up-a-hugo-site-on-github-pages-with-submodules%2Fimg%2Fgithub-pages-settings.jpg" alt="menu to update Github Pages settings to use master branch"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With these settings, Github Pages will be able to serve our site from the repo starting with the &lt;strong&gt;index.html&lt;/strong&gt; file in its root directory. The live URL for the site is built from your user name and the project name. Here’s my sample URL - &lt;a href="https://aormsby.github.io/hugo-gh-pages-public" rel="noopener noreferrer"&gt;https://aormsby.github.io/hugo-gh-pages-public&lt;/a&gt;. At this point, our site won’t display anything except an error message since Hugo requires some page templates or a full theme to generate the pages. That’s fine. We just wanted to add some stuff to Github so we could access the repo’s Github Pages settings as we just did.&lt;/p&gt;

&lt;h2&gt;
  
  
  Benefits of Making a Submodule in ‘Public’
&lt;/h2&gt;

&lt;p&gt;To recap, here’s our project setup so far.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.adamormsby.com%2Fposts%2Fhow-to-set-up-a-hugo-site-on-github-pages-with-submodules%2Fimg%2Fsubmodules-diagram-with-public.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.adamormsby.com%2Fposts%2Fhow-to-set-up-a-hugo-site-on-github-pages-with-submodules%2Fimg%2Fsubmodules-diagram-with-public.jpg" alt="project submodule digram with public folder"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let’s take a look at some of the benefits of this system.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;No accidental deploys&lt;/strong&gt; - With our source code separated from our site data, it’s a lot harder to accidentally push unfinished work to our live site. Even if we make builds locally and push our source changes, we won’t push to our &lt;strong&gt;hugo-gh-pages-public&lt;/strong&gt; repo without explicitly running commands to make that happen. &lt;em&gt;*sigh of relief*&lt;/em&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Separate rollbacks&lt;/strong&gt; - If something goes wrong, the main project and public project can be separately rolled back to earlier commits. &lt;em&gt;(Just remember to commit the modified reference updates to the main module!)&lt;/em&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Branch work is easier&lt;/strong&gt; - Changing branches in our source project will not change branches in our subproject (and vice versa). This is another nice safety buffer, and it gives us more options for branching in either module.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Ready for site staging&lt;/strong&gt; - We can easily create development branches in the &lt;strong&gt;public&lt;/strong&gt; submodule that could be served as development subdomains of our site and used for testing new features.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Some Drawbacks
&lt;/h3&gt;

&lt;p&gt;Of course, it’s always wise to assess the risks of any setup, and there are many opinions on the ‘perfect system’ in the dev world - &lt;strong&gt;tell me about yours in the comments!&lt;/strong&gt; To shine some light on the potential downsides of our submodule use, here are some of the concerns I’ve thought about.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Juggling multiple repos&lt;/strong&gt; - With more submodules comes more administration. It doesn’t seem so rough for me, but right now I’m working on my own. Running interlinked, asynchronous repositories comes with its own challenges in a team setting, particularly if someone forgets to push updated submodule references to the source.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;No site staging with Github Pages&lt;/strong&gt; - While the &lt;strong&gt;public&lt;/strong&gt; submodule can branch and easily store data used in a site staging system, Github Pages does not seem to support subdomains from different project branches. That’s more of a Github Pages drawback, but it means we can’t take full advantage of our setup just yet. Another hosting platform might offer a solution - I’ll be looking into some options in a future post.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Add a Theme to Our Site
&lt;/h2&gt;

&lt;p&gt;Wait, we’re not finished just yet! Remember how our site doesn’t display anything except an error message right now? We need some templates to get things up and running. The easiest way to get some is to add one of the many &lt;a href="https://themes.gohugo.io/" rel="noopener noreferrer"&gt;Hugo themes&lt;/a&gt; to our project. Since I’m already using it on this site, I’ll use the &lt;a href="https://themes.gohugo.io/hugo-theme-hello-friend/" rel="noopener noreferrer"&gt;Hello Friend theme&lt;/a&gt; in my example.&lt;/p&gt;

&lt;p&gt;Many guides for adding a theme - including Hugo’s own docs - just tell you to clone the theme repo or download and copy it into your project’s &lt;code&gt;themes&lt;/code&gt; directory. But hey, &lt;em&gt;our&lt;/em&gt; theme today is &lt;em&gt;submodules&lt;/em&gt;, so I propose that we add a theme to our project as a &lt;em&gt;submodule&lt;/em&gt; since doing so would give us some nice dev powers over the theme.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.adamormsby.com%2Fposts%2Fhow-to-set-up-a-hugo-site-on-github-pages-with-submodules%2Fimg%2Fsubmodules-diagram-with-theme.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.adamormsby.com%2Fposts%2Fhow-to-set-up-a-hugo-site-on-github-pages-with-submodules%2Fimg%2Fsubmodules-diagram-with-theme.jpg" alt="project submodule digram with theme folder"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Look at it this way - directly cloning a theme into our project has two major problems.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;We can’t push our commits to the theme’s source repo, because we don’t have permission.&lt;/strong&gt; This means we can’t make changes to the theme and then keep them versioned.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A cloned project in a subdirectory isn’t linked with the main project.&lt;/strong&gt; When a submodule is added to a project, the main project adds a reference to it in a file named &lt;code&gt;.gitmodules&lt;/code&gt;. Without that reference, the main project and the theme project aren’t connected, which could cause confusion or problems down the line.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Also, Git doesn’t allow repos inside repos that aren’t submodules.&lt;/strong&gt; See &lt;a href="https://wespeter.com/posts/avoiding-git-problems-when-installing-a-theme-to-hugo/" rel="noopener noreferrer"&gt;this ‘simple dev’ post&lt;/a&gt; for details.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let’s solve each of those problems in one fell swoop.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Make a fork of the &lt;strong&gt;Hello Friend&lt;/strong&gt; theme so we have our own copy of it.
&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.adamormsby.com%2Fposts%2Fhow-to-set-up-a-hugo-site-on-github-pages-with-submodules%2Fimg%2Ffork-theme.jpg" alt="fork a theme project on Github"&gt;
&lt;/li&gt;
&lt;li&gt;Add our forked repo as a submodule in our main project’s &lt;code&gt;themes&lt;/code&gt; folder.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Add the theme submodule from the root project folder
# my sample URL - https://github.com/aormsby/F-hugo-theme-hello-friend.git
&amp;gt; git submodule add https://github.com/[GITHUB_USERNAME]/[FORKED_THEME_REPO_NAME].git themes/hello-friend

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

&lt;/div&gt;



&lt;p&gt;Boom! Now we have our own fork of a cool theme referenced as a submodule of our Hugo project. We can make any changes we want and push them to our own repo. I’ll get into more advanced uses of theme submodules in another post, but for now we have the basics in place.&lt;/p&gt;

&lt;p&gt;Things won’t be &lt;em&gt;quite&lt;/em&gt; right without tweaking a few final settings, so let’s open the &lt;code&gt;config.toml&lt;/code&gt; file in our project root so we can modify a few lines.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Add a line so our site builds using our new theme.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;theme = "hello-friend"

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

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Because we’re making a Github ‘project site’ we want to change the&lt;code&gt;baseURL&lt;/code&gt; to match our project URL.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;baseURL = [GITHUB_USER_NAME].github.io/[PROJECT_NAME]

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

&lt;/div&gt;



&lt;p&gt;For example, mine will say &lt;code&gt;aormsby.github.io/hugo-gh-pages-public&lt;/code&gt;. To understand the difference between setting up a project site and a user/organization site, see these &lt;a href="https://pages.github.com/" rel="noopener noreferrer"&gt;Github Pages&lt;/a&gt; and &lt;a href="https://gohugo.io/hosting-and-deployment/hosting-on-github/#github-user-or-organization-pages" rel="noopener noreferrer"&gt;Hugo&lt;/a&gt; docs on the matter.&lt;/p&gt;

&lt;p&gt;There are a lot more theme settings that can be adjusted in your config file, but you can explore those on your own. Let’s deploy!&lt;/p&gt;

&lt;h2&gt;
  
  
  Test Site and Deploy
&lt;/h2&gt;

&lt;p&gt;Running the terminal command &lt;code&gt;hugo server&lt;/code&gt; in our project root spins up a local live preview of our site that can be viewed in a browser at &lt;code&gt;localhost:1313&lt;/code&gt;. Run this now to check if our site is displaying anything (it should!), and then stop the process with &lt;code&gt;Ctrl+C&lt;/code&gt;. Just like we did before, run the commands to build, commit, and push. &lt;em&gt;(Note that we didn’t change anything in the theme, so we don’t have to push anything in that repo.)&lt;/em&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;gt; hugo
&amp;gt; cd public
&amp;gt; git add .
&amp;gt; git commit -m "build with theme"
&amp;gt; cd ../
&amp;gt; git add .
&amp;gt; git commit -m "build with theme - update submodule reference"
&amp;gt; git push -u origin master --recurse-submodules=on-demand

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

&lt;/div&gt;



&lt;p&gt;After a few minutes, refresh the live site at &lt;code&gt;https://[USER_NAME].github.io/hugo-gh-pages-public&lt;/code&gt; and check out your new site! Congratulations, you’ve done it!&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Theme Branches and Getting Updates&lt;/strong&gt; - I’ve worked out a nice branch-based system for continuing to get updates from the original theme repo while adding and changing things our forked theme repo. It’s super useful. &lt;a href="https://www.adamormsby.com/posts/hugo-themes-making-modifications/" rel="noopener noreferrer"&gt;Next post!&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.adamormsby.com/posts/hugo-shell-deploy-script/" rel="noopener noreferrer"&gt;Better Deploy&lt;/a&gt; - I’m sure you noticed that we had to use &lt;em&gt;a plethora&lt;/em&gt; of terminal commands to add, commit, and push files to the main project and its submodules to maintain proper commit references. I wrote them out in this post for clarity, but this process is definitely something we can automate. Hugo’s docs provide a &lt;a href="https://gohugo.io/hosting-and-deployment/hosting-on-github/#put-it-into-a-script" rel="noopener noreferrer"&gt;basic deploy script&lt;/a&gt; to do this, and I’m working on a greatly improved version of it that I’ll write about when it’s ready for action.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Custom domains / CNAME&lt;/strong&gt; - You may want to set up a custom domain on Github Pages. Here’s &lt;a href="https://help.github.com/en/github/working-with-github-pages/configuring-a-custom-domain-for-your-github-pages-site" rel="noopener noreferrer"&gt;some good documentation&lt;/a&gt; on how to do that.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Thanks for reading! ~&lt;/p&gt;

</description>
      <category>hugo</category>
      <category>jamstack</category>
      <category>githubpages</category>
      <category>submodules</category>
    </item>
    <item>
      <title>Hugo Themes - Making Modifications while Keeping the Source Up-To-Date</title>
      <dc:creator>Adam Ormsby</dc:creator>
      <pubDate>Tue, 29 Sep 2020 22:00:00 +0000</pubDate>
      <link>https://dev.to/aormsby/hugo-themes-making-modifications-while-keeping-the-source-up-to-date-2m11</link>
      <guid>https://dev.to/aormsby/hugo-themes-making-modifications-while-keeping-the-source-up-to-date-2m11</guid>
      <description>&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.adamormsby.com%2Fposts%2Fhugo-themes-making-modifications%2Fcover.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.adamormsby.com%2Fposts%2Fhugo-themes-making-modifications%2Fcover.jpg"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Overview
&lt;/h2&gt;

&lt;p&gt;In today’s post, I want to take a look at how we can keep our Hugo themes up-to-date. ‘But my theme works fine!’ you say. ‘Why would I ever need to update it?’ Well, when you download or clone a Hugo theme from its hosted git repository, you’re getting its latest version &lt;em&gt;at that point in time.&lt;/em&gt; So even if the theme’s creator pushes updates to the code - with fixes, new features, and outside pull requests - you’ll still be stuck using the version you downloaded before. While this is fine in some cases, many of us want the newest updates so we can take advantage of a stronger, improved theme.&lt;/p&gt;

&lt;p&gt;The key to this process is using git submodules to track and pull updates to a theme with just a few quick commands. If you followed my previous tutorial on &lt;a href="https://dev.to/aormsby/how-to-set-up-a-hugo-site-on-github-pages-with-git-submodules-pbc-temp-slug-1243121"&gt;adding a theme to your Hugo site as a git submodule&lt;/a&gt;, you already have a functional Hugo site with a (forked) theme included. Starting there, let’s see how to connect our theme to its remote source repo, which git commands we need to update it, and even how to safely make our own custom changes to the theme while keeping it in line with the source.&lt;/p&gt;

&lt;h2&gt;
  
  
  Just the Updates, Please
&lt;/h2&gt;

&lt;p&gt;If we don’t intend to customize a theme at all, we can keep our workflow super simple. All we need to do is add the theme repo into our project as a submodule and periodically run a few git commands to check for updates. For the moment, let’s pretend we haven’t forked the theme repo and see what it would be like to clone the source directly. We’ll see an example with our fork in the next section.&lt;/p&gt;

&lt;p&gt;Here’s a quick refresher command for adding a submodule to our project.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt; git submodule add https://github.com/panr/hugo-theme-hello-friend.git themes/hello-friend

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

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;You might be thinking you can simply run &lt;code&gt;git clone&lt;/code&gt; instead of adding the theme as a submodule, but our site is already set up as a git repo so that doesn’t work here. Git doesn’t like having &lt;code&gt;.git&lt;/code&gt; files in a subdirectory without a &lt;code&gt;.gitmodules&lt;/code&gt; component in the root. For more on that, see &lt;a href="https://wespeter.com/posts/avoiding-git-problems-when-installing-a-theme-to-hugo/" rel="noopener noreferrer"&gt;this ‘simple dev’ post.&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In the example above, we added our submodule by pulling the theme’s source repo directly into our project. With the &lt;code&gt;git remote&lt;/code&gt; command, we can easily verify that it’s connected to the correct remote repo.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt; cd themes/hello-friend
&amp;gt; git remote --verbose
origin https://github.com/panr/hugo-theme-hello-friend.git (fetch)
origin https://github.com/panr/hugo-theme-hello-friend.git (push)

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

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.adamormsby.com%2Fposts%2Fhugo-themes-making-modifications%2Fimg%2Fsimple-update.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.adamormsby.com%2Fposts%2Fhugo-themes-making-modifications%2Fimg%2Fsimple-update.jpg" alt="one-way update directly from theme source"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And there it is! With this setup, all we need to do is pull updates straight from the source. From the theme’s directory, we run the following terminal commands.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# optional: fetch any updates to view changes before merging
&amp;gt; git fetch origin
&amp;gt; git status
[status output here]

# pull updates and merge them automatically
&amp;gt; git pull

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

&lt;/div&gt;



&lt;p&gt;Since we’re not making any theme changes in this workflow, we shouldn’t expect any merging issues during the &lt;code&gt;git pull&lt;/code&gt;. We don’t really &lt;em&gt;need&lt;/em&gt; to fetch or check the status of the repo, but it’s always nice to see incoming changes before we bring them in.&lt;/p&gt;

&lt;p&gt;And that’s it! Getting updates every so often is no problem if we don’t intend to make our own customizations to a theme. But hey - customization is where the fun &lt;em&gt;really&lt;/em&gt; begins.&lt;/p&gt;

&lt;h2&gt;
  
  
  Updates and Theme Customization - A Parallel Branch Workflow
&lt;/h2&gt;

&lt;p&gt;Here’s the scenario - We want to add a Hugo theme, make custom changes, and still to get updates from the theme’s original source. The method used above doesn’t work here for a few reasons:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;We can’t push our custom changes to the theme’s source repo&lt;/strong&gt;. We simply don’t have those permissions on the repo. Our local changes will not be safely stored anywhere, and any pulled updates may not be easily mergeable.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Incoming updates may require merges.&lt;/strong&gt; If we’ve modified some of the theme files that are being updated in the source, then a simple &lt;code&gt;git pull&lt;/code&gt; will not be enough to deal with the resulting conflicts.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Thankfully, a more advanced git workflow would help deal with these issues. Remember &lt;a href="https://www.adamormsby.com/posts/how-to-set-up-a-hugo-site-on-github-pages-with-submodules/#add-a-theme-to-our-site" rel="noopener noreferrer"&gt;how we set up a forked theme repo&lt;/a&gt; in the last post? Now we get to take advantage of it. Crucially, the forked repo is &lt;em&gt;ours&lt;/em&gt;, so we have full write access to it and don’t need to worry about repo permissions. We can do whatever we want.&lt;/p&gt;

&lt;h3&gt;
  
  
  Add a Remote Repo
&lt;/h3&gt;

&lt;p&gt;However, our fork doesn’t automatically receive source updates either! Here, an additional step is needed to link our fork back to the source repo. Earlier, in the direct update workflow, we used the &lt;code&gt;git remote&lt;/code&gt; command to verify that we had the correct remote repo connections. Running it in our forked theme directory, we see only the fork as our remote.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# my forked repo URLs as an example
&amp;gt; git remote --verbose
origin https://github.com/aormsby/F-hugo-theme-hello-friend.git (fetch)
origin https://github.com/aormsby/F-hugo-theme-hello-friend.git (push)

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

&lt;/div&gt;



&lt;p&gt;To get updates from the source repo, we need to add a &lt;em&gt;second&lt;/em&gt; remote repo - yes, git can do this! We simply run this command in our working directory and check our remotes again to verify the connection.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# add a new remote repo connection
&amp;gt; git remote add upstream https://github.com/panr/hugo-theme-hello-friend.git

&amp;gt; git remote --verbose
origin https://github.com/aormsby/F-hugo-theme-hello-friend.git (fetch)
origin https://github.com/aormsby/F-hugo-theme-hello-friend.git (push)
upstream https://github.com/panr/hugo-theme-hello-friend.git (fetch)
upstream https://github.com/panr/hugo-theme-hello-friend.git (push)

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

&lt;/div&gt;



&lt;p&gt;Ta-da! Our local theme repo is now linked to both our forked repo &lt;em&gt;and&lt;/em&gt; the source repo, which we called &lt;code&gt;upstream&lt;/code&gt;. (This is a conventional label, but any name you choose is fine.) At this point, our setup already supports getting updates from the source, but the process is a little different than before.&lt;/p&gt;

&lt;p&gt;Normally, when we’re updating directly from a single remote repo, all we need to do is &lt;code&gt;pull&lt;/code&gt; the data to our local directory so that the local matches the remote. We’ll still do that here, but we explicitly pull data from the &lt;code&gt;upstream&lt;/code&gt; repo we added. We’ll also have to make an additional &lt;code&gt;push&lt;/code&gt; to our forked repo - &lt;code&gt;origin&lt;/code&gt; - to update it with the new code. Here’s how that works compared to the previous example.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.adamormsby.com%2Fposts%2Fhugo-themes-making-modifications%2Fimg%2Fforked-update.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.adamormsby.com%2Fposts%2Fhugo-themes-making-modifications%2Fimg%2Fforked-update.jpg" alt="comparison of update methods"&gt;&lt;/a&gt;Left: simple update / Right: updating with a fork&lt;/p&gt;

&lt;p&gt;Assuming you’re still on your &lt;code&gt;master&lt;/code&gt; branch, here are the modified commands needed to pull and push the updates.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# optional: fetch any updates to view changes before merging
&amp;gt; git fetch upstream master
&amp;gt; git status
[status output here]

# pull updates and merge them automatically
&amp;gt; git pull upstream master

# push source updates to forked repo
&amp;gt; git push origin master

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

&lt;/div&gt;



&lt;p&gt;With no local changes to our theme, the commands run smoothly with no errors - and we want to keep it that way! Simple is good, and an update process that doesn’t result in merge conflicts is always nice. But how do we manage to avoid conflicts if we want to customize the theme? Simple - don’t do your work on &lt;code&gt;master&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Branching, Customizing, and Merging Updates
&lt;/h3&gt;

&lt;p&gt;Although you technically &lt;em&gt;could&lt;/em&gt; make theme customizations on the &lt;code&gt;master&lt;/code&gt; branch, this increases the chances of having to resolve merge conflicts every time you try to pull an update. It’s fine if that’s how you want to work, but I &lt;em&gt;highly&lt;/em&gt; recommend avoiding it. In my experience, it’s often best to keep &lt;code&gt;master&lt;/code&gt; sparkly clean and do your dirty work on a different branch.&lt;/p&gt;

&lt;p&gt;For example, I do my theme in a separate branch that is always kept in parallel with &lt;code&gt;master&lt;/code&gt;. I’ve named it &lt;code&gt;working&lt;/code&gt;, as it’s the branch that I &lt;em&gt;work&lt;/em&gt; in. (Not exactly clever, I know.) Since it has all of my theme customizations, it’s also the branch that I use when I build my site. Every so often, I switch back over to &lt;code&gt;master&lt;/code&gt;, go through our update process, and then explicitly merge any new theme updates from &lt;code&gt;master&lt;/code&gt; into &lt;code&gt;working&lt;/code&gt; so that I have all the latest features in my working branch. Visually, it’s kind of like this.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.adamormsby.com%2Fposts%2Fhugo-themes-making-modifications%2Fimg%2Fparallel-branches.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.adamormsby.com%2Fposts%2Fhugo-themes-making-modifications%2Fimg%2Fparallel-branches.jpg" alt="parallel branch system with updates merged from master"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is just one possible theme customization workflow, but we can benefit from a setup like this. For example –&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Our workspace is separate from our update environment.&lt;/strong&gt; Getting theme updates will always be a painless process, and we have more control over merging when the time comes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Commit histories are clearer.&lt;/strong&gt; Histories are much easier to read if source updates and custom work don’t get tangled up, and this can be super helpful when performing more advanced git actions on a branch.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;All the data is on our forked repo.&lt;/strong&gt; The customizations &lt;em&gt;and&lt;/em&gt; the pulled updates all live on our fork, which means we have full control of the data.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;We can test on &lt;code&gt;master&lt;/code&gt; before merging.&lt;/strong&gt; If we’re unsure of how a new feature will display on our site, we can run a build using the &lt;code&gt;master&lt;/code&gt; code. It’s a nice clean test bed before performing a merge.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The drawbacks are much the same as I mentioned in the &lt;a href="https://www.adamormsby.com/posts/how-to-set-up-a-hugo-site-on-github-pages-with-submodules/#some-drawbacks" rel="noopener noreferrer"&gt;last post&lt;/a&gt; with the addition that now we’d have at least one more working branch to manage. However, I’ve found this parallel branch workflow quite nice after getting more familiar with it. Perhaps you will, too.&lt;/p&gt;

&lt;p&gt;Here are the commands we can use to get our &lt;code&gt;working&lt;/code&gt; branch up and running. (You can choose a better name if you’d like.)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# create a new branch and switch to it
&amp;gt; git branch working
&amp;gt; git checkout working

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

&lt;/div&gt;



&lt;p&gt;We make some changes, commit our work, and push to our forked repo (&lt;a href="https://www.adamormsby.com/posts/how-to-set-up-a-hugo-site-on-github-pages-with-submodules/#test-site-and-deploy" rel="noopener noreferrer"&gt;see these commands for help&lt;/a&gt;). Time passes… and we want to get some updates on &lt;code&gt;master&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;# switch to master branch
&amp;gt; git checkout master

# quick update
&amp;gt; git pull upstream master
&amp;gt; git push origin master

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

&lt;/div&gt;



&lt;p&gt;Finally, we switch back to &lt;code&gt;working&lt;/code&gt; and merge in the updates from &lt;code&gt;master&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;# switch to working
&amp;gt; git checkout working

# merge master into current branch (working)
&amp;gt; git merge master

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

&lt;/div&gt;



&lt;p&gt;I won’t get into resolving a merge here, so let’s cross our fingers and hope there are no conflicts to deal with.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.adamormsby.com%2Fposts%2Fhugo-themes-making-modifications%2Fimg%2Fgit-merge-conflict.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.adamormsby.com%2Fposts%2Fhugo-themes-making-modifications%2Fimg%2Fgit-merge-conflict.jpg" alt="git merge conflict comic"&gt;&lt;/a&gt;something to look forward to :)&lt;/p&gt;

&lt;p&gt;So yes - customizing your theme with this kind of workflow does take a bit of setup, and there are a few extra steps and things to keep track of to manage our code well. However, using git submodules and a parallel branch workflow do give us more leverage over our codebase, and I think that makes the extra work worthwhile. I’ve been using this workflow with my site for some time, and I don’t think I’d change anything about it.&lt;/p&gt;

&lt;p&gt;That said, there are a number of other methods that people use for managing their themes, and it’s worth exploring them to see what fits your needs best. I recently read a post about &lt;a href="https://www.hugofordevelopers.com/articles/master-hugo-modules-managing-themes-as-modules/" rel="noopener noreferrer"&gt;managing your themes as Hugo modules by Nick Gracilla&lt;/a&gt; that I found quite interesting, and I think it’s worth checking out if you’re looking for an alternate way of doing things.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.adamormsby.com/posts/hugo-shell-deploy-script/" rel="noopener noreferrer"&gt;Better Deploy&lt;/a&gt; - I’m still working on a better site deploy script! It’s looking good so far, but it’s not quite ready.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Automatic Builds&lt;/strong&gt; - This would still be great to have, so if I get around to it I’ll be sure to share my work.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Until next time! ~&lt;/p&gt;

</description>
      <category>hugo</category>
      <category>jamstack</category>
      <category>githubpages</category>
      <category>submodules</category>
    </item>
    <item>
      <title>Build and Deploy: A Shell Script for Hugo Sites</title>
      <dc:creator>Adam Ormsby</dc:creator>
      <pubDate>Mon, 22 Jun 2020 04:30:00 +0000</pubDate>
      <link>https://dev.to/aormsby/build-and-deploy-a-shell-script-for-hugo-sites-15he</link>
      <guid>https://dev.to/aormsby/build-and-deploy-a-shell-script-for-hugo-sites-15he</guid>
      <description>&lt;h2&gt;
  
  
  Shell Scripts are Awesome
&lt;/h2&gt;

&lt;p&gt;I don’t know about you, but I &lt;em&gt;love&lt;/em&gt; writing code that automates my work. I finally had the chance to do just that, and now I’m the proud owner of a shell script that builds and deploys my Hugo site without any extra help from me - and it even works with my git submodule setup!&lt;/p&gt;

&lt;p&gt;So why do this? Well, when I began working with Hugo, I ran across a &lt;a href="https://gohugo.io/hosting-and-deployment/hosting-on-github/#put-it-into-a-script" rel="noopener noreferrer"&gt;rudimentary deploy script&lt;/a&gt; in their documentation. Since I was still familiarizing myself with Hugo, it hadn’t occurred to me yet to automate the build process, and I immediately fell in love with the idea. However, I could see the script would need major improvements to do what I wanted, and I was completely new to shell.&lt;/p&gt;

&lt;p&gt;At first, I struggled a bit with writing shell code (especially keeping things POSIX-compliant for portability!), but I stumbled upon the &lt;a href="https://www.shellscript.sh/" rel="noopener noreferrer"&gt;shellscript.sh&lt;/a&gt; tutorials and dove straight in. Thanks to those &lt;em&gt;fantastic&lt;/em&gt; tutorials, I now have a sweet script to show off and perhaps even a newfound love for the shell. Apart from variable expansion struggles, it’s really quite elegant!&lt;/p&gt;

&lt;p&gt;I find my &lt;code&gt;hugo-deploy.sh&lt;/code&gt; script does help keep builds following a standard process, but I think I’ll really see it shine when I get around to scheduling automated builds on a remote server. Exciting!&lt;/p&gt;

&lt;p&gt;full script at end&lt;/p&gt;

&lt;h2&gt;
  
  
  Deploy Script Functionality
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;Be sure to place this script in your &lt;strong&gt;site’s root directory&lt;/strong&gt; if you intend to use it. It’s built with my git submodule setup in mind. But I don’t think it would be too hard to modify it for something different.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Order of Operations
&lt;/h3&gt;

&lt;p&gt;From start to finish, here’s what the script does.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Update the automatic build number (included in the git commit)&lt;/li&gt;
&lt;li&gt;Check for any user options (see below)&lt;/li&gt;
&lt;li&gt;Check if your active repo branches match your intended deploy branches

&lt;ul&gt;
&lt;li&gt;Production and development branches can both be set&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Check if your local repo is up to date (no merge conflicts allowed!)&lt;/li&gt;
&lt;li&gt;(Optional) Clear out the site output folder before the Hugo build&lt;/li&gt;
&lt;li&gt;Run Hugo build command&lt;/li&gt;
&lt;li&gt;Git add, commit, and push to your specified remotes&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If any point in this process fails, the script exits with an error message detailing where the issue occurred. You’ll have to fix the issue before running the script again. Thankfully, most of the issues are quick fixes. If you have to do a merge, that’s on you!&lt;/p&gt;

&lt;h2&gt;
  
  
  ‘Settings’ Variables
&lt;/h2&gt;

&lt;p&gt;There are some ‘settings’ variables at the top of the script that you may need to modify to match your project.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# BUILD/DEPLOY SETTINGS - edit as needed for your use case

PUB_SUBMODULE="public" # name of output folder where git submodule is located
IGNORE_FILES=". .. .git CNAME" # space-delimited array of files to protect when 'fresh' option is used
DEV_BRANCHES="dev dev" # development branches to build on and push to, 1-root, 2-pubmodule
PROD_BRANCHES="master master" # production branches to build on and push to, 1-root, 2-pubmodule

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

&lt;/div&gt;


&lt;p&gt;&lt;code&gt;PUB_SUBMODULE&lt;/code&gt; holds the name of the folder where your public site submodule is located. The default output folder is &lt;code&gt;public&lt;/code&gt;, which is where I have my submodule for the live site. If you’ve changed your output folder in the site config, you’ll need to update this to match it. The variable value is relative to the root directory, so if you’ve buried your output folder then set the path accordingly (e.g. &lt;code&gt;my/public/build&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;&lt;code&gt;IGNORE_FILES&lt;/code&gt; is used with the ‘fresh’ option (see below). It acts as an array of filenames that will &lt;em&gt;not&lt;/em&gt; be deleted from the output folder if you select the ‘fresh’ option. It’s mostly to protect non-Hugo files.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;PROD_BRANCHES&lt;/code&gt; are the two production branches on which you intend to build and push your site data. The first branch name matches the preferred deploy branch for your &lt;strong&gt;site source data&lt;/strong&gt; (in your root directory), and the second branch name matches the preferred deploy branch for &lt;strong&gt;your live site&lt;/strong&gt; (the supposed submodule). These are the values the script uses to check your active branches in step 3 above. It’s a nice safety check.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;DEV_BRANCHES&lt;/code&gt; works the same way for a development build, which is enabled through the user options.&lt;/p&gt;
&lt;h2&gt;
  
  
  User Options
&lt;/h2&gt;

&lt;p&gt;Sometimes you need a little customization! That’s where my included script user options come into play. Hopefully these options can help you out a bit.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Script Options
./hugo-deploy.sh [-d|-f] [-m "COMMIT_MESSAGE"] [-o "HUGO_OPTIONS"]

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

&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;-d&lt;/strong&gt; ‘dev’ =&amp;gt; deploys to development branches set in DEV_BRANCHES list (default is PROD_BRANCHES)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;-f&lt;/strong&gt; ‘fresh’ =&amp;gt; deletes public directory data before rebuild (skips files in IGNORE_FILES list)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;-m&lt;/strong&gt; ‘message’ =&amp;gt; appends a custom commit message to the auto-build string, works exactly like git -m&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;-o&lt;/strong&gt; ‘options’ (for Hugo build) =&amp;gt; includes Hugo build options during deploy process (default none), all &lt;code&gt;hugo build&lt;/code&gt; options are valid&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;-h&lt;/strong&gt; =&amp;gt; ‘help’
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Usage Example
./hugo-deploy.sh -d -f -m "Deploying like a rockstar!" -o "--cleanDestinationDir"

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

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Fun Stuff:&lt;/strong&gt; If you rename the script file to &lt;code&gt;hugo-deploy.command&lt;/code&gt;, you can run the script with a double click! I haven’t actually tested this, but I think it just runs without options. Try it out!&lt;/p&gt;
&lt;h2&gt;
  
  
  Disclaimers / Seeking Shell Wisdom
&lt;/h2&gt;

&lt;p&gt;I ran into some issues with this script that I couldn’t totally avoid. Please be aware of them if you try out my script.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Variable expansion&lt;/strong&gt; - I’m aware that the variables I use in my various git commands are not double-quoted. (And just in case I didn’t notice, &lt;a href="https://www.shellcheck.net/" rel="noopener noreferrer"&gt;ShellCheck&lt;/a&gt; yelled about them in bright colors.) However, adding quotes or modifying the expansion caused the commands to be incorrectly formatted and resulted in failure. They work as they are now, but I’m curious to know if there’s a way to improve this. I’d love to get advice from experienced shell coders.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Limited Testing&lt;/strong&gt; - I work on Mac OS, so I &lt;em&gt;know&lt;/em&gt; this script works on that system - at least on my machine! I have no idea about Windows or Linux. If you try it out, please let me know!&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  The Full Script
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://gist.github.com/aormsby/fac42fa04f8afa2157109b85684edc0c#file-hugo-deploy-sh" rel="noopener noreferrer"&gt;View on Github&lt;/a&gt;&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



</description>
      <category>hugo</category>
      <category>shell</category>
      <category>githubactions</category>
      <category>automation</category>
    </item>
  </channel>
</rss>
