Half-Elf on Tech

Thoughts From a Professional Lesbian

Author: Ipstenu (Mika Epstein)

  • JSON to Markdown

    JSON to Markdown

    Now that I understand how Hugo and JSON work separately and together, it’s time to figure out the next question.

    Can I generate Markdown files based on the contents of a JSON?

    My JSON File

    I started with an SQL DB where my photos have lived for a long time. I exported the albums table to a JSON file (yes, phpMyAdmin can do that), cleaned it up by removing the cruft I didn’t need, and ended up with something like this:

    [
     {
        "categories": "Adventures",
        "tags": "Index",
        "folder": "foobar",
        "title": "Foobar and Baz",
        "desc": "The adventures of Foobar and Baz.",
        "date": "2006-03-24 19:46:40"
      },
      {
        "categories": "Vacations",
        "tags": "Index",
        "folder": "botbob",
        "title": "Bot and Bob",
        "desc": "Bot and Bob's vacation photos",
        "date": "2006-03-24 11:51:04"
      }
    ]
    

    By the way, I’m not going to address how to actually make the gallery with images here. Yet. The eventual idea I have here is to run this with WordPress doing that, but since I was messing around with this anyway, I figured I’d reuse what I had.

    The end goal here, remember, is to export the JSON file from WordPress (list all top level categories, let’s say) and have Hugo generate a page for each one. That’s all. But WordPress has so much data, I decided to start with the smaller, simpler stuff.

    Let’s move on.

    Create a Markdown Page from JSON

    Thankfully someone else has already tossed this idea around. I started with reading Dynamic Pages with Hugo

    My idea is: Import any JSON or CSV from any local file or URL and make the JSON or CSV content available in a shortcode or directly in the layout files.

    That was very close to what I wanted, but it would result in me having to make a page for each item. I don’t want that. I want a script to make the .md file for me.

    So I stepped back and stopped asking “How do I make a Hugo page from JSON?” and I asked “How do I make a separate file for each entry in a .json file?”

    Sidebar: My wife was trying to convert the Hebrew year (3595) into all the possible other calendars and asked me to help her with the math. I asked her “What Julian year is that?” She said it BCE so it didn’t work like that, but that was 167. I Googled “What is 167 BCE in the Chinese calendar?” Boom. WikiPedia’s page for 167 BC lists them all. As I pointed out, the trick to these things is not converting it all yourself, but getting from ‘weird’ to ‘Base 10.’ Once you’re at the default (the lowest common denominator), it’s allot easier to figure out other people’s weird.

    This is related to my task at hand. Weird is being specific. Weird is caring what system I’m using. The root of my issue is this: I want to make a Markdown file for every entry in JSON.

    I use Mustache. And, yes, someone already had this idea. He was using mustache-render in Grunt, which I’m already familiar with, but I made a few changes.

    1. I changed the templates folder to my Hugo Archetypes folder. This is my source, my style.
    2. I changed the data folder to my Hugo Data folder.
    3. The output went to (you got this one, right?) the Hugo Content folder.

    This should work, right?

    Mustache Render

    My Gruntfile has this:

        mustache_render: {
          all: {
            options: {
              directory: "partials"
            },
            files: [
              {
                data: "../data/parents.json",
                template: "../archetypes/gallery.mustache",
                dest: "../content/gallery.md"
              }
            ]
          }
    

    And my gallery.md file is like this:

    ---
    title: {{title}}
    author: Me
    layout: default
    permalink: /{{folder}}/
    categories: {{categories}}
    tags: {{tags}}
    ---
    
    {{title}}
    

    Except that doesn’t work. If I changed {{title}} to {{0.title}} then it showed Foo and Bar’s adventure information. Obviously the render was only going to show each entry individually. Now. This could work in a variety of situations, just not mine. Alternatively, I can wrap the output in this: {{#0}} ... {{/0}}

    But what I want is ‘for each key in json, make a file…’ and since I can put the JSON output right into the gruntfile (data: { greeting: "Hello", target: "world" }) then in theory I want to generate this:

    files: [
      {data: OUTPUT FROM KEY ,
       dest: KEY ID,
    ]
    

    Okay so how do I tell Grunt to read from a JSON and for each key, do a thing? First I use grunt.file.readJSON:

    pkg: grunt.file.readJSON('../data/parents.json'),
    
        mustache_render: {
            [...]
                files: [{
                    template: '../archetypes/gallery.mustache',
                    data: '<%= pkg.1 %>',
                    dest: '../content/<%= pkg.1.id %>-foo.md'
                }]
          }
        }
    

    And this will output item #2 (Bob’s vacations). So stage one is complete. Now I want the 1 in pkg.1 to be iterative or I want to pass a variable to the mustache file and change {{#0}} ... {{/0}} based on its value. Obviously if I had one JSON file for each ‘post’ I wanted to make, this would be easy.

    Multiple Markdown Files from One JSON

    I have no idea.

    Seriously. I spent a few hours on this, lying in bed trying to feel less cold-and-flu-ish. At this point, I don’t really care what I use to do it, but the bones is this: Take one JSON file and split each object into it’s own file.

    Can’t figure that out yet. But hey, there’s my 2016 project!

    FYI: If you reply with ‘try project X!’ without a code example of how to do it, I’ll probably delete your comment. I’ve seen ‘Try handlebars!’ or ‘Try Assemble’ but my issue here is no one has an example of how to do it, and I work best by example. I need that Hello World.

    I am looking at Handlebars and Assemble, by the way, but at 900+ words, it’s time to call a pause on the adventure.

  • Using JSON with Hugo

    Using JSON with Hugo

    I know I’ve been talking about Hugo a lot, but the whole reason I say and wrapped my head around it was that I wanted to make a website using JSON.

    Making something out of the JSON API in WordPress isn’t easy, and I decided to start with something hard. I thought I would make a Multisite network to be the back end of my site, and then call the JSON API to generate the content.

    Why?

    It doesn’t make my site (much) faster, though it makes it more cacheable. Mostly what it does is lets me separate church and state. I can use WordPress to write content, and then call it however I want. That would be Hugo. If I build the site via Hugo locally, then every time I generate the files it can pull in the data on the fly.

    Enable the API

    This is easy. Install WordPress 4.4 and install v2 of the Rest API plugin. I also installed Jetpack for reasons of using Calypso.

    You absolutely have to use the Rest API plugin. WordPress 4.4 adds in some of the bits, but the API plugin gives you the actual endpoints. You’ll need these later.

    Call the API

    This was also easy. Kind of. Making a jquery file that called the content was fairly straightforward but… Making it responsive and reactive was hard.

    What I really wanted to do was have some web app, js powered without node, that just called the data and kept the url structure. And for that what I need is a JSON client.

    It was incredibly hard to find how to make a static HTML website powered by JSON. I’d see Rachel Baker’s presentation on making a WordPress theme with the JSON API but that wasn’t what I wanted to do. I mean, in a way it was. The theme itself was what I wanted, but I didn’t want to run it with WordPress.

    I did a lot of research and finally stumbled onto restful.js by marmelab. I read their blog post on the product and it looked like what I wanted. I needed something that would run without Node.js since I wanted to do this on Apache.

    Consuming a RESTful Web Service Dynamically

    And this is when I starting banging my head against a table. None of the solutions I’d found were working for me. Nothing. Rachel was right. I was in a bit over my head. Oh she was nice enough not to say it that way, but they way she looked at me was very Jewish Mom of her.

    In order to stop feeling useless, I decided to learn Hugo. It had come up a few times on my search for a dynamic static site. Hugo has LiveReload which, if you’re familiar with most static generators, is pretty cool. The idea is the pages rebuild as you edit the content (or theme) files.

    If you run hugo server locally on your laptop, you can see this today. Hugo upped the ante by tossing in the ability to run it on the server and the ability to watch the data files. It also has the ability to call JSON remotely.

    I feel it’s important to note that you cannot trigger that LiveReload when you’re using external URLs. But anytime you edit a file and LiveReload is triggered, Hugo will read the URL content from your cache. If you’ve disabled cache, it will download it fresh. Don’t disable cache unless you have an unlimited API. And no, I don’t know how long the cache is good for.

    Sadly, OAuth or other authentication methods are not working yet, but for now that’s okay because I’d been in over my head for so long, I stepped back.

    Understanding JSON First

    Okay fine. Once I realized I’d tried to do too much at first, I went back to that static filmography I had.

      {
      	"role": "actor",
        "title": "White Christmas",
        "slug": "white-christmas",
        "type": "Movie",
        "character": "Phil Davis",
        "notes": null,
        "dates": 1954
      }
    

    This is basic stuff. A simple chunk by chunk. And to call the file in a shortcode, I did this:

    {{ range $.Page.Site.Data.filmography }}
    	{{ if eq $role .role }}
    		<li>{{ .title }}: <strong>{{ .character }}</strong> </li>
    	{{ end }}
    {{ end }}
    

    Actually I did a lot more but you get the idea. And if you’re wondering about the if statement at the top, it’s so I can pass a parameter to my shortcode:

    {{< filmography role="actor" >}}

    It took me longer than I’d like to figure that out. At first I had multiple filmography files (actor, writer, producer) and I was trying to look through them all. In the end, I realized this simple JSON and a simple call was better.

    A Little More JSON

    There was another case, though. I had lists of episodes compiled into separate JSON files, one per show. This is logical and maintainable after all, but it meant I couldn’t use the same logic loop in the same way.

    What I really needed was to loop through $.Page.Site.Data.episodes.SHOWNAME in order to get the data from that show. And I couldn’t add on a variable to my range call.

    But as it happens, Hugo is clever and if I say {{ range $.Page.Site.Data.episodes }} it will give me the file episodes.json if that exists. But if there happens to be a folder called episodes then it will give me all the JSON files in there.

    I read through the data documentation on Hugo a few times to understand the hierarchy but it breaks down really logically:

    ├── data
    |   ├── episodes
    |   |   ├── continum.json
    |   |   └── fringe.json
    |   |   └── sense8.json
    |   ├── movies.json
    |   ├── musicals.html
    

    Data {dot} episodes {dot} continum

    And if I ran this:

    {{ range $.Page.Site.Data.episodes }}
    	<li>{{ .show }}<li>
    {{ end }}
    

    Then I got this:

    • continum
    • fringe
    • sense8

    I already knew I could do a range within a range, and finally I came up with this:

    {{ $show := $.Page.Params.show }}
    
    {{ range $.Page.Site.Data.episodes }}
    	{{ if eq .show $show }}
    		<li>{{ .title }}</li>
    	{{ end }}
    {{ end}}
    

    The shortcode checks the post it’s on and, if the Front Matter has ‘show’ defined, it will give me a list of all titles (episode titles) for that show.

    I added in an extra check for the season parameter. This one is passed through the shortcode:

    {{< episodelist season="1" >}}

    And that, in turn is called in the shortcode above the output for title:

    {{ range where .episodes "season" "==" $season }}

    So nothing will display unless the show in the JSON file matches the show on the page with the shortcode, and the season matches the one defined in the shortcode.

    Now I actually have a more robust check. If no season is defined, it shows all episodes (useful for one-season shows, right?). But you get the idea.

    How Did This Help?

    Remember my JSON example before? Here’s what it looks like for Fringe:

    {
    "show" : "fringe",
    "episodes": [
      {
        "epnum": "1",
        "season": "1",
        "title": "Pilot",
        "slug": "pilot",
        "airdate": "2008-09-08T22:00:00.000Z",
        "rating": "5",
        "summary": "Walter gets a cow named Gene to experiment on ethically."
      },
      ...
    ]}
    

    Instead of just started with those naked chunks, I have a definition of the show name (fringe – lowercase because I want to compare it to other lowercase things and I’m lazy) and the definition of a section for episodes. That’s the whole reason why that call for seasons works the way I want it to.

    This helped me to understand and visualize JSON. By taking a simple JSON list (the filmography) I learned the basics of connecting code and content. Then by taking the more complex scenario, where I needed nested data, I understood that relationship.

    The next step will be making a simple WordPress site and calling the JSON remotely. Obviously I have to figure out how to trick it into making fake permalinks, but baby steps. Baby steps.

  • The Fiscal Responsibility of 25%

    The Fiscal Responsibility of 25%

    “We’re going to deploy on December 20th.”

    I winced.

    I’m not Christian and December 25th is just another day when I binge watch Netflix. The 24th? Movie night! But I picked up a habit at the Bank and that was not deploying code for the last two weeks and first two weeks of the year unless the company was going to be fined if we didn’t.

    I was brutal about that to people. I was harsh and mean and demanded lengthy justifications. I made them speak to senior management, who were hard to find around that time of year because every one was on vacation.

    The reason for this was that the bank had a clear cut fiscal responsibility not to go down between Thanksgiving and a bit after New Years. That was when year end processing happened, and that was when many companies who used us were processing the most orders. For a lot of people, business booms right when everyone wants to take a break to be with their family.

    WordPress runs 25% of the Internet.

    We use it for blogging, for building Facebook-eqsue sites, for running ecommerce stores.

    That means and we the developers of WordPress now have a responsibility not to break when we upgrade people. A huge responsibility. And it’s one we can never give with 100% assurance because of one simple fact.

    We made WordPress open.

    Anyone can make a theme or plugin. And while we do our best to test with core WordPress, we cannot test all of the 45k plugins in the repository yet. The best is maybe we could write a script to check for fatal errors on activation. But even then, can we test all 45,000 against all possible permutations of combinations?

    That’s an incredibly massive number. All my factorial calculators, even Google, just said ‘Infinity.’ And we add about 9000 plugins a year. This is staggeringly huge and it gets bigger every year

    But with this increase in share and use comes an incredible responsibility to 25% of the web. We cannot break their sites.

    Of course I know that’s impossible. There will always be outliers. And even with the large user base that companies like Yoast have, the dearth of willing and capable Beta Testers for a free product is going to bite us. It’s part of what I asked what I did at the Town Hall at WCUS — Are we going too fast?

    Speed cannot exclude us from a responsibility to our users. And with the increasing provenance of online stories and websites for everyone, pushing a change when we know that the majority of the world is celebrating something between Nov 15th and January 15th is reckless. Look at how many people want time off in those months to be with family. Look at how many businesses are running sales. Look at the amount of data transfer that spikes.

    And then picture what happens when an update has a small bug that takes down one site in a thousand. 1/1000 of 1/4th of the entire Internet. If that didn’t make you shiver, do the math again. Imagine if Apple went down because they pushed an update right around Christmas?

    The answers change sometimes, though. What if it was a security fix? Would that change your mind? It would change mine. A major upgrade around Christmas worries me. A minor one, not so much.

    It may be time to call a year end moratorium on updates to our systems and apps. If they’re business and mission critical, test them as best you can, but consider if you have to update before that Christmas rush. Make people jump through hoops to prove they need the new shiny right now. If you know you’re understaffed or under heavy load, consider that as much as anything else.

  • Looping Hugo

    Looping Hugo

    I’m ending the year with something non-WordPress. But it has a weird JSON related journey.

    I asked three questions at the end of my last post:

    1. How do I properly mimic a for-loop with range?
    2. Can I make a responsive gallery out of Hugo?
    3. Can I power a Hugo site with WordPress JSON?

    This is the answer to the first one. However in the solving, I made a breakthrough in my head about how one calls data from JSON and structures it.

    But I’m getting ahead of myself, becuase changing a for loop from Jekyll to Hugo was harder than I expected. Way harder.

    One of the things I check in some posts is what the rating is. I set a parameter called ‘rating’ and if it’s there, I ran a quick check to determine how many stars to show:

    <strong>Rating:</strong> {% if page.rating %}{% for i in (1..page.rating) %}<i style="color:gold;" class="fa fa-star" name="star"></i>{% endfor %}{% if 5 > page.rating %}{% assign greystar = 5 | minus: page.rating %}{% for i in (1..greystar) %}<i style="color:grey;" class="fa fa-star" name="star"></i>{% endfor %}{% endif %}{% else %}<em>Not Available</em>{% endif %}
    

    I was pretty damn proud of that loop. Check the rating, output a gold star for each number over 0 and a grey star for every number between the rating and 5. It’s simple but it’s quick.

    Transposing from Liquid to GoLang was not as hard as all that. {% %} became {{ }} and {% endfor %} became {{ end }} and, at first, that was the easy stuff. The majority of my logic was a one-to-one translation. Change page.rating to .Params.rating and so on and so forth.

    The order of the if’s was strange to me, in that it became {{ if eq A B }} (except when it wasn’t) and I was used to thinking {% if A == B %} — it was fairly easy to overcome. In short order, all my simple if-checks were done.

    But those damn loops! I had the ugliest “if A == 1, show 1 gold and 4 grey” configuration. And worse, I had cases where I was checking “If there’s an entry in the Filmography for this show, get the rating from that and not the page itself.” The Filmography file was a straight-forward JSON file, you see (told you JSON was involved).

    Back to the first problem. I knew if I wanted a shortcode to say “Get me a list of all pages, by date, where section is news” I did this:

    {{ range where $.Page.Site.Pages.ByDate "Section" "news" }}

    And that $.Page.Site.Pages.ByDate call changed depending on what template I was on and what I was calling. For a shortcode I had to pass though page to site to pages. On a template I could do .Data.Pages.ByTitle (no $ needed either). I’m still at the trial and error stage of figuring out which call and where, but I know I’ll get there. It’s just mastering new syntax and understanding where I’m calling from and what variables are available to me.

    That’s really okay. It took me years to visualize the interrelations with WordPress themes and functions and plugins, and even then sometimes I’ll output an array in ugly, unformatted ways just to read through and make sure I understand what I’ve got at my disposal. This is normal for most of us.

    And it was fairly clear that if I wanted a shortcode to call the data file and not a list of Section pages, there was code for that: $.Page.Site.Data.filmography (back to Filmography again). And that worked fine. Right up until I wanted to say “For all values where X equals Foo…” and I was back to my loop-headache.

    Now. GoLang does have a for loop!

    func main() {
        sum := 0
        for i := 0; i < 10; i++ {
            sum += i
        }
        fmt.Println(sum)
    }
    

    And I though that I could just use that. Nope! So I asked myself why did {{ for i in (1..Params.rating) }} fail?

    First of all, that ‘in’ should be := instead. But even so, when I ran it I got “ERROR: function “for” not defined.” That means there is no for function. And no loop. After looking at how I was iterating in other places, I did this:

    {{ range $index, $element := .Params.rating }} 
       ONE
    {{ end }}
    

    ERROR: 2015/12/12 template: theme/partials/rating.html:3:26: executing “theme/partials/rating.html” at <.Params.rating>: range can’t iterate over 3 in theme/partials/rating.html

    The 3, in that case, had to do with a rating of 3. This makes a little sense, since you’re supposed to use range to iterate over a map, array or slice. A number is none of those.

    Thankfully I found a ticket talking about adding a loop function to Hugo that was addressing what I was trying to do and finally I had an answer:

        {{ range $star, seq .Params.rating }}
            <i style="color:gold;" class="fa fa-star" name="star"></i>
        {{ end }}
    
        {{ $greystar := sub 5 .Params.rating }}
    
        {{ range $star, seq $greystar }}
            <i style="color:grey;" class="fa fa-star" name="star"></i>
        {{ end }}
    

    The idea there is that seq makes a sequence of the value of .Params.rating for me. If the value is 3, I get an array of [1,2,3] to work with. And that’s something range can itterate over!

    Except…

    at <sub 5 .Params.rating>: error calling sub: Can’t apply the operator to the values in theme/partials/rating.html

    Now the amusing thing here is that the code worked! Even if it wasn’t seeing .Params.rating as an integer, it did the math. I suspect it’s related to this old bug, where variables from front matter are strings and not integers. Except that he said it worked in YAML and that’s what I’m using.

    This was the most perplexing issue. How is a number not a number if it’s being numbered? And then I noticed that I was able to make a sequence, so clearly at that point it knew it was a number. And then I did this:

        {{ $goldstar := seq .Params.rating }}
        {{ $goldstar := len $goldstar }}
    

    And yes it works.

    I’m basically saying “Hey, how many ones are in the number X?” and saving that as a number. There’s no real reason I can comprehend why it failed to work, but there it is. I’ll file a bug as soon as I can figure out how to explain that in a way that doesn’t make me sound crazy.

    How did all this teach me about JSON? You’ll have to wait a few days.

  • Porting Jekyll to Hugo

    Porting Jekyll to Hugo

    Importing content is always the bane of moving systems.

    Now one of the things Hugo has is a cool command called $ hugo import jekyll – and yes, it does exactly what you think it does. This was interesting to me since I wondered if I could switch my library from Jekyll to Hugo and yes, yes I can.

    The site I have on Jekyll has a few more posts than the first one I built on Hugo. This one has around 1500 pages. Excited, I ran the command:

    Importing...
    Congratulations! 0 posts imported!
    

    That’s not right. I spent a few hours trying to run it in various permutations, but I was never able to get it to run right. Thankfully, I didn’t need to since I could just copy my content over. There was no translation needed, as I was already using yaml headers in my .md files so that actually was a pretty painless transition.

    The theme on the other hand… Well. I had a complex site with data files and weird junk being thrown around. That was just learning how to translate for-loops for ranges, with some where clauses tossed in.

    Was it hard? Yes. But that’s not what you’re really asking.

    Was it worth it?

    Excuse me while I whip this out:

    Change detected, rebuilding site
    2015-12-11 21:42 -0800
    0 draft content
    0 future content
    1479 pages created
    0 paginator pages created
    16 categories created
    66 tags created
    in 4611 ms
    

    Yes. The site builds faster, which is a win. It also creates tags and categories that can automatically cross link. I can make ‘sections’ without having to define them in my config file, just by making folders. I can spin up templates quickly. I have a little more redundancy than I’d like, but as I master GoLang, this becomes less and less.

    Build time ranges from 11737 ms to 2116 ms. Milliseconds. They were into the minutes with Jekyll, even though Jekyll 3 was notably faster than version 2. It was still taking me about 2 minutes to rebuild the Jekyll site, even with incremental builds working. Plus I had to build and rsync every time, in addition to Git pushing. Now I just Git and done.

    Oh and JSON works remotely out of the box. I just have to get better at my range calls now.

    What’s Different?

    Making a ‘static front page’ with Hugo is harder. In fact there’s still an open trac ticket on it. I was able to use an idea I already had, a custom post param called “type” for tagging ‘index’ posts in the news pages so I didn’t get a list of my indexes when I wanted to list all news from 2002. I leveraged that and tagged my primary index ‘mainindex’ and put a quick check in my index.html in my theme:

    {{ range .Data.Pages }}
        {{if eq .Type "mainindex" }} 
            {{ partial "content.html" . }}
        {{end}}
    {{ end }}
    

    Instead of doing a normal loop where, like a blog it shows me posts in reverse order, it just showed that specific content.

    But…

    If there’s a file in that Section with the type of ‘Index’ then it shows that. Of course… While index.md doesn’t get used in the main content folder, it does in Sections. If I have a file named index.md in a section, that makes index.html like I expected. Since I still wanted lists in the majority of cases, I tweaked the content of my default list file (list.html) so that I could always show a ‘main’ file:

        {{ range .Data.Pages.ByTitle }}
            {{ if eq .Type "index" }}
                {{ .Content }}
            {{ end }}
        {{ end }}
    
        <ul>
        {{ range .Data.Pages.ByTitle }}
            {{ if ne .Type "index" }}
                <li><a href="{{ .Permalink }}">{{ .Title }}</a></li>
            {{ end }}
        {{ end }}
        </ul>
    

    Then I renamed all the index.md files in the Sections to main.md but this created another issue. Now I had two URLs that worked. I could have put this into the template for the section to avoid this, but I want to separate content and theme as much as humanly possible. WordPress habits. For now, I’ve left this alone. If someone is clever enough to go to a non-linked, non-sitemaped page instead of the index, I think my SEO will live. It’s more than I wanted to play around with loops.

    Speaking of the loops and lists, getting a list of a ‘sub section’ is not currently possible either. Rather, they do work, but there’s no default templates for sub-sections. This was a small problem since I structured my site like this:

    .
    └── content
        ├── news
        |   ├── index.md          // /news/
        |   ├── 2001
        |   |   ├── loch-ness.md  // /news/2001/loch-ness/
        |   |   └── monster.md    // /news/2001/monster/
        |   └── 2002
        |       ├── nessie.md     // /news/2002/nessie/
        |       └── spock.md      // /news/2002/spock/
        └── posts
    

    Now, I don’t need a custom template for each sub-section, but I did want to use my custom list template for each sub-section. To work around this, I made a template in /layout/section/news.html that had this:

    	{{ range .Data.Pages.ByTitle }}
    		{{ if and (eq .Type "index") (ne .Params.topic "index") }}
    			{{ .Content }}
    		{{ end }}
    	{{ end }}
    

    I know this is weird. The Type of index means “I am the main index file of the section” while the topic index means “I am an indexing file and not a normal news article. This gives me my main index of /news/ giving me a custom content page with information like I wanted, using the main.md format I use in all sections.

    Then in each sub-section, I use a very simple index.md file:

    ---
    title: News Articles (1992)
    author: Mika Epstein
    layout: news
    topic: index
    date: 1992-01-01
    permalink: /news/1992/
    categories: ["News"]
    tags: ["1992"]
    ---
    
    {{< news >}}
    

    That weird bit in the content is a shortcode ala Hugo, which calls the file /layouts/shortcode/news.html that has this:

    {{ $date := $.Page.Date.Format "2006" }}
    
    <table class="infobox">
    
        <thead><tr>
            <th>Date</th>
            <th>Source</th>
        </tr></thead>
    
        <tbody>
        {{ range where $.Page.Site.Pages.ByDate "Section" "news" }}
            {{ $thisdate := .Date.Format "2006" }}
    
            {{ if and (eq $date $thisdate) (ne .Params.topic "index") }}
    
                <tr>
                    <td>{{ .Date.Format "01 January" }}</td>
                    <td><a href="{{ .Permalink }}">{{ .Title }}</a></td>
                </tr>
    
            {{ end }}
        {{ end }}
        </tbody>
    </table>
    

    That spits out a table of all the pages in that section by date.

    What’s Next?

    It took a lot to get here, or so it may seem. This took me two nights to work out. That’s it. So now I have to figure out the next steps that have vexed me:

    1. How do I properly mimic a for-loop with range?
    2. Can I make a responsive gallery out of Hugo?
    3. Can I power a Hugo site with WordPress JSON?

    And that’s a whole ‘nother story.

  • Mailbag: Hugo from iPads

    Mailbag: Hugo from iPads

    So I’ve done the whole Hugo thing and it’s great and it totally works for me. That 1% itch left from Jekyll is gone. So queue the inevitable…

    But what about mobile posting?!

    Why on earth the planet is obsessed with posting everything from their phone, I don’t know. Things like Instagram and Twitter make it easy for us to ‘communicate’ (and I use that loosely) and post photos of our lunch. And yes, the iOS app for the iPhone means I can ‘live blog’ but, to be honest, I hate it on my iPhone.

    My iPad though… I love posting from that.

    And yes, yes I can post to my Hugo run site from my iPhone or iPad. Remember, I can push my new content by running a git push command. The server will build, sync, and clean up on its own. All I need to do it is a Git app on my iPad that doesn’t suck

    Working Copy does not suck.

    It’s an iOS app that pulls my git repository to my iPad (the whole thing, so make sure you have room). Then I can edit files, commit them, and push. Hugo on the server does the rest, just like it would from my desktop.

    Working Copy is different from many other Git related apps because can hook into any git repository. I’m not using GitHub for this project. I want to do 100% self hosting, and that means no GitHub. Also no BitBucket. These tools are fine for what they are, and in fact I pay GitHub for some private repos. But I wanted my repo on my server, in part so I could do exactly what I’m doing.

    The tool is incredibly simple. It’s a familiar file navigator, tap through the folders. Tap edit to edit, make changes to the post, hit done. There’s even a preview feature that mostly works. Some of my Markdown files are very weird.

    If I wanted to edit in Byword, which is what I do most of my writing in for non-novel related things, I can share and go back and forth. I’d love it if the WordPress iOS app (or Calypso) did that. Write in Byword, send to other app. But even a copy/paste is simple enough. In this case, I can write in Byword and share to Working Copy. The interface takes the title of my document and let’s me pick the folder.

    Once I’m done with my edits, I commit my changes. Then I can push, or not. There’s an option to commit+push, but it crashed my app. A skim of reviews showed this happened to others. The iOS interface can be a bit tetchy so having this be two steps doesn’t bother me.

    I did find it odd that there was no button to push. I had to go back to the main folder, swipe-left, and press the orange push button. But that, and the weird crash, were it for annoyances.

    While free to download, it’s $9.99 for unlimited deployments. It was free for 3 weeks, which I tried out over WordCamp US and found simple and perfect for my workflow.