Also, a good tool to help you debug here is running Ghost in development mode because it’d inform you if your filter is erroring out. Starting Ghost in dev mode is part of this tutorial:
Inside the {{post}} context, inside the {{#if @custom.show_recent_posts_footer}} condition.
But…I worked it out. The correct syntax to match on all tags, in order of the number of matches, is:
{{#get "posts" filter="id:-{{id}}+tags:[{{tags[*].slug}}]" as |more_posts|}}
There is no . between tags and [*].
Also, there are two syntaxes:
Singular tag to match on just one tag: {{#get "posts" filter="id:-{{id}}+tag:{{primary_tag.slug}}" limit="3" as |more_posts|}}
Plural tags to match one or more tags in a comma-separated list/array: {{#get "posts" filter="id:-{{id}}+tags:[{{primary_tag.slug}}]" limit="3" as |more_posts|}}
Both of the above work and achieve the same result because the list of tags in the second example is only given one tag to match.
To match on all the post’s tags you need +tags:[{{tags[*].slug}}].
Thanks for inspiring me to figure this out, @RyanF.