Skip to main content

Senior Web Engineer. Open web / music. Remote DJ. Tall Dutch guy. #3million



WordPress Canonical URLs for Category/PostName Permalinks

When the permalink format is set to %category%/%postname%/ then a post is available under category/postname links for all categories, as well as under all parent/child/postname links.

If you use Yoast SEO and have set a primary category, that  becomes the canonical URL that's used for SEO. If you don't then the postname for whatever category has a lower ID (was created first) becomes the canonical URL.


What is the meaning of a site's Last Updated property?

When running a WordPress multisite, in the site directory each site has a Last Updated property. I previously incorrectly assumed this reflected  when the site's metadata changed, for example the site's attributes. However, archiving and deactivating a site does not change the Last Updated value, so what does it do in WordPress 5.2.1?

As usual the best place to look is the WordPress codebase. It turns out that, on a multisite, this value is updated whenever a post is updated or deleted. It reflects the last content update, not the site's metadata.

By inspecting the html and looking up the property name, we find that the function that updates this is called wpmu_update_blogs_date and there is an action hook wpmu_blog_updated that receives the site_id variable. This function can be called whenever we want to update the value. It isn't used anywhere else.

If we're looking to update this date whenever the site's status changes, then via the same process it appears that he actions to hook into site attribute updates are in wp_maybe_transition_site_statuses_on_update so one could write a quick mu-plugin that updates the Last Updated property whenever these fire.


The Milk Chocolate Peanut

Aaron Gustafson wrote back in 2008:

Getting into the progressive enhancement mindset is quite simple: just think from the content out. The content forms the solid base on which you layer your style and interactivity. If you’re a candy fan, think of it as a Peanut M&M:

The Chocolatey Layers of Progressive Enhancement

JavaScript first websites have the peanut inside out!


Generating Atom feeds from your Lektor site

After quickstarting a Lektor site, a next obvious thing to do is to add a feed to the site's blog. Fortunately, Lektor has a growing ecosystem of plugins, one of them creates atom feeds.

Installation of lektor-atom

The plugin to install is lektor-atom, and is installed via the terminal:

lektor plugin add lektor-atom@0.2
lektor build

This adds a reference to the myproject.lektorproject file with the plugin and installs the plugin into the lektor pipeline.

Configure a feed

However, notice that after building the site no feed is generated! This is because no feeds have been setup yet.

Create a configs/atom.ini containing the following lines (full documentation)

name = My Blog feed
source_path = /blog
item_model = blog-post
url_path = /blog/feed.xml

Change the url_path to suit your preferences. Trying to build now would result in an error: E blog/feed.xml (RuntimeError: To use absolute URLs you need to configure the URL in the project config.)

To resolve the build process myproject.lektorproject must be updated with two lines within the project section to indicate the site's live URL and an absolute URL style:

name = My Project
url =

lektor-atom = 0.2

The site can then build and the resulting feed can be accesssed from


Building on temporary foundations

Just came across an interesting perspective on frameworks by Timothy Perrett:

It is imperative to understand that the need for composability in our software tools is an absolute requirement. If we as an industry have any hope of not repeating ourselves time and time again, we have to change our ways.

I definately agree that we're doomed to keep making the same mistakes if we're building on top of frameworks and then switching them out for a different one, which I hadn't considered before.


Fork webpages

I'm looking for something a bit unusual. Say you are following the instructions for installing a software package (rl example: Now you find out the instructions are outdated, or incomplete.

How do you keep your notes/additional instructions together with the original? Now you have two problems, your instructions and the original can be updated independently. What happens when the original is updated, or a new version of the software is released?

Wouldn't it be great if you could fork the webpage and update it (or even submit a pull request to the maintainer)?

Is there any practical way of working this way - or will I be stuck with a notetaker / blog / bunch of outdated textfiles?

A lot of questions - maybe one of you has the answer.


Link: Stop paying your jQuery tax

Speed up your jQuery powered site by moving scripts to the footer.

Turns out that pushing jQuery to the footer is quite easy for the common case. If all we want is a nice $.ready function that we have accessible everywhere we can explicitly define it without jQuery. Then we can pass the functions we capture to jQuery later on after it loads.

The big lesson learned is that we could avoided this whole problem if we started off with my proposed helper.

via Stop paying your jQuery tax.


Hide elements that will be shown by jQuery later

I stumbled upon this gem by Jerph on Stackoverflow:

Right after the body tag, put a script tag with this javascript:


This gives you a style hook for any elements that will look different in some way when Javascript enabled, and it happens immediately.

via css - Hide jQuery Accordion while loading - Stack Overflow.


Asynchronous UIs - the future of web user interfaces

Discovered this javascript MVC framework SpineJS. The ToDo app is extremely impressive. Try and manipulate items as quickly as possible. Tthen close and reopen the browser. Nice.

via Asynchronous UIs - the future of web user interfaces.


Combining multiple Subversion repositories

This post describes a step by step guide on how to combine multiple Subversion repositories whilst keeping individual history (and commit messages).


Exporting from pagefeedbacktool repository the /trunk/public folder and integrating that into the services repository under /trunk/public/pagefeedback:

Dump the repository including only /trunk/public as follows:

E:\\Repositories\\pagefeedbacktool>svnadmin dump .| svndumpfilter include --drop-empty-revs --renumber-revs trunk/public > ..\\services\\filtered.dump


However as pathnames are stored as part of the dump (and replacing the path with a texteditor corrupts the dump), we have to include the full path under a different parent directory:

In VisualSVN create a /trunk/public/pagefeedback/trunk/public folder structure (try without the final public if import fails) then load the dump as follows:

E:\\Repositories\\services>svnadmin load . --parent-dir "trunk/public/pagefeedback" < filtered.dump

The dump is successful but at the wrong path:

currently: /trunk/public/pagefeedback/trunk/public
should be: /trunk/public/pagefeedback/


Open two Windows Explorer windows with both paths side by side, select all the files that should be moved, then RIGHT click drag them to the destination folder and choose SVN Move versioned files here...

Commit from the repository root.

It is now safe to remove the trunk/public folders under /trunk/public/pagefeedback/

Commit again.



HOWTO Use UTF-8 Throughout Your Web Stack

Unicode can be an issue that's hard to resolve, so it's guide to use the guidance in this document and ALWAYS use unicode where possible.

via HOWTO Use UTF-8 Throughout Your Web Stack updated for terminal use

After publishing the previous article about - the shell script I created to easily serve websites in development - I made some changes to make it easier to run it from the terminal, for example over ssh. I thought I'd share it with you.

One of the problems with the original script was that it was optimized for a GUI setting - ie. start the script by clicking on it from the desktop. However usually I want to run it from the terminal. I don't like typing so I added code to make the script available from any directory to the ~/.bashrc:

export PATH=$PATH:~/bin

Then moved it to that path and renamed it to shave another 3 characters off the syntax:

mv ~/Desktop/ ~/bin/serve

In addition I noticed that prompting which site should be served was just a workaround for commandline arguments, which are now added. It doesn't check that you entered an argument though. So the new script now requires you to specify which directory you want to serve: to serve the current directory simply run:

serve .

Latest script contents:

my_path=`readlink -f $1`
sudo rm /var/www
sudo ln -s $my_path /var/www
echo Now serving $my_path... - A shell script for serving sites

I am experimenting with using a Linux virtual machine as my web development environment of choice. I store the vm on a removable drive so that I can develop from any location, without having to setup a working environment. Previously I had to check out the repositories, setup a local webserver and I had trouble keeping things working, because every configuration change had to be applied in every location. Now it is all centralized and my life is simpler.

The aim is to make working on projects as easy as possible. I have all projects checked out in a folder called /var/sites. They are mostly PHP projects and because of my shared hosting environment they share a single apache configuration. How can I easily serve them? Having seperate virtualhosts for each project would result in me having to make manual changes on every location again, so this was not the way to go.

Instead I created a simple shell script that creates a symbolic link from the Apache's webroot to the project I am working on:

[gallery link="file"]

echo "Available sites:"
ls  /var/sites
echo -n "Type site to serve: "
read site
if [ -z "$site" ]
sudo rm /var/www
sudo ln -s /var/sites/$site /var/www


Intranet Migration Strategy

Next week we're turning off our old intranet site so I have setup a "Migration Switch" and a redirection page so that from the moment we turn off the site people will not be able to access it. Because if we actually turn off the site we would receive phonecalls with people needing access to their lost data, and because certain parts of the old intranet are reused in our new one, we instead check if the page is embedded, and if it's not check that the user is on a whitelist of specifically allowed users (us). If this is not the case we redirect them.

Next week we will remove all navigation links to the old intranet, turn on the switch, and remove the documents from the search indexer on the (new) intranet. There must be better terminology for old and new intranet.

Hopefully this will ensure that everything works smoothly.


Subversion repository creation rule

Do not use capitals for repository names!
Because when checking out a working copy you will have to specify the respository url case sensitive. Failing to provide the correct case sensitive name result in things might appear to work but you might get access forbidden messages for certain users in some point, and other mysterious errors, such as the svn commit error below:

access to '/svn/project/!svn/act/c50e0f11-eec3-154a-9695-20ec222ad7f3' forbidden


Amasan's WordPress Tweak Roundup

Made few tweaks to improve the blog in preperation for several drafts I'm currently working on. Here's a quick rundown for everyone that's interested in the wordpress blog platform.

  • Related Posts should show up to 5 related posts without too many false positives on single article pages. I like how this plugin scores posts on relativity and that I can set it to show nothing when no posts are related, which keeps the interface clutter to a minimum.
  • A single easy recognisable block of Google Adsense adverts has been added to single articles. You won't see it if you have Adblock Plus installed like myself, but it should give helpful suggestions on articles with a single subject and support hosting costs in the process.
  • Template tweak: Moved post-meta-information from under the title to the footer (tag/cat info) so that the header is better connected with the body of the post. There's enough clutter on other sites.
  • I've visually combined  categories and tags underneath articles. Category are used for url purposes and tags  to facilitate cross linking of subjects. No need for two lists.
  • I added a tagcloud to the site so you can browse the site and discover some other articles. I don't think browsing by time and month is useful to many people so that's been removed from the site. The only concern I have at the moment is that the cloud would grow to too big a list, so in the future I might just show the top 7 tags used. For now that's not a problem.
  • PHP Speedy. This is the most important reason why the site is so snippy.

There's more but I'll save them for another time.


Youtube Dreamweaver CS3 Tips

Brian Wood presents an excellent Dreamweaver tips video on Youtube. Many people just use DW as a text-editor but it's capable of a lot more even in code view. The following video might open your eyes:

Very nice.


Improving someone's code

Don't call your submit button 'submit' if you want to change the submit event with Javascript:

If you do, the browser (please read “Firefox 1.5 or IE 6? - that’s what I tested at the moment) will consider submit is an object. And an object is not a function (although you might enjoy later on the paradox that a function is an object).

Source []