Half-Elf on Tech

Thoughts From a Professional Lesbian

Tag: moving

  • 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.

  • Changing Your Domain Name In Multisite

    Changing Your Domain Name In Multisite

    Even I hate moving Multisite if I have to change folders (like from domain.com/wordpress to domain.com). But if you told me “Mika, I need to change my domain from cocobanana.com to cocoabanana.com!” I’d say “Hold my beer for five minutes.”

    No. 2 pencilsI will note: If this process freaks you out, remember to never make changes like this without a backup. If it’s still super spooky, you may not be ready for Multisite yet. I would consider this to be a good litmus test, though, for a wanna-be-multisite-master. You’re going to need to be able to do these things to get there.

    Step 1: Search and Replace

    This is the easiest one. If you have WP-CLI it’s super easy.

    wp search-replace http://cocobanana.com http://cocoabanana.com
    

    Don’t have WP-CLI? Okay, grab Interconnectit’s Search/Replace DB Tool and use that.

    This will take care of 99.999999% of your site. It’s imperative you remember to use this tool! If you don’t use a tool that searches and replaces with consideration to data serialization, you will cry and reset all your themes and widgets. Manually. See? Told ya you’d cry!

    Step 2: Edit the Database

    Go into the database. Look at the wp_site table. Change the domain field from cocobanana.com to cocoabanana.com (seriously, that was it!).

    Then look at wp_blogs and change those domains similarly as needed.

    Step 3: Edit wp-config.php

    Open the file and look for this:

    define('DOMAIN_CURRENT_SITE', 'cocobanana.com');
    

    Change the value to cocoabanana.com and save it.

    Step 4: .htaccess and plugins

    I lied. There’s another step. Make sure you weren’t super smart earlier. Like if you used some rules to block hotlinking, make sure the new domain is added in there. Also make sure your plugins aren’t calling your domain in some weird way (though that search and replace should have fixed that too).

    Also if, like me, you hate www’s in your URLs, you’ll want to put this in your .htaccess to force everyone around. It also has the benefit of making sure the weird redirect of www being treated as a subdomain stops happening on Multisite. By the way, I still strongly encourage you to NOT use www in your Multisites, it’s a pain in the ass and you can educate people as to why no one has to have www anymore. Also WordPress itself has always suggested you NOT use it when activating Multisite. Do you know better than WordPress? No? Okay then, don’t use www.

    &amp;lt;IfModule mod_rewrite.c&amp;gt;
    	RewriteEngine On
    	RewriteBase /
    	RewriteCond %{HTTP_HOST} ^www\.(.*)$ [NC]
    	RewriteRule ^(.*)$ http://%1/$1 [R=301,L]
    &amp;lt;/ifModule&amp;gt;
    

    Now can I have that beer back?

    Beer and a cup

  • Migrating A WordPress Site With wp-cli

    Migrating A WordPress Site With wp-cli

    This is … crazy simple. I wanted to move a site from ipstenu.org to ipstenu.com (yes, I own that too). While ipstenu.org is a Multisite network, ipstenu.com is where I put a ton of add-on domains. I was moving a site over and, as it was WordPress, did it in a matter of minutes.

    Add the domain to the … domain

    Since I don’t care to have multiple hosting accounts, and I’m the only one with SSH/FTP access, it’s safe enough for me to do this. There is a risk when you share multiple domains in one hosting account, that if one gets hacked they’re all vulnerable, but I consider it low in my situation. Every plugin is vetted, every file is checked, and then I went and gave each add-on it’s own FTP account. Neurotic? Thy name is me.

    Anyway, I add the new domain to my hosting where I want it.

    Create the new DB

    I have to make a new database, and generally a new DB user, on the server too.

    Export!

    On existing hosting, I do this:

    wp db export
    

    That gives me my SQL file, thanks to WP-CLI. It’ll be named example_com.sql and will sit in my folder with .htaccess and everything else.

    Copy!

    I do it via SSH. I go to the new location and run this:

    scp -r olduser@example.com:path/to/files/ .
    

    Since I have ssh keys set up, it’s easy. If I don’t, I’ll put in the password, but that’s straightforward.

    Edit wp-config.php

    Now I have to point to the new DB. Sometimes I name it the same, but usually I don’t, so I’ll edit the DB name, DB user, and password.

    Import the old DB

    Ready?

    wp db import example_com.sql
    

    Boom. It’s all dumped in! Only two steps left!

    Search & Replace

    I love this one.

    wp search-replace example.com newexample.com --dry-run
    

    I ALWAYS dryrun test it. This is a serialization safe search, so rarely is it ever going to be an issue to just run, but it lets me make sure I don’t get any wonky results. I never have, so re-run without dry-run.

    Cleanup!

    Delete the SQL file, delete the old files on the old server.

    Drink

    El Chorro Margarita

    I moved code. That’s shipping, right? Or is it margaritas are for migrations?