question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Feature: Internal Tags - Tags for Structure & Workflow

See original GitHub issue

We’ve made pretty huge progress in terms of all the new tag features that were outlined in Tags 101, as well as massively overhauling all of the UIs related to tags.

One feature we’ve not looked at adding yet, is adding two levels of ‘Visibility’ so that we can have a concept of hidden tags. This feature has been referred to as ‘private’ tags, however I think it may be a good idea to not use the word ‘private’ as everywhere else private data explicitly refers to data that you must be authenticated to see (draft posts vs published) and this idea is not related to auth. I’m using ‘hidden’ as that’s the name of the column in the database, but ‘system’ or ‘internal’ might work too.

Problem

At the moment, every tag you add to a post is the same. They all get listed on a post when it is published, and also get their own tag page / archive that lists out all of the posts. This makes perfect sense for tags which are meant to be a front-facing taxonomy, but limits the system so that tags cannot be used for workflow or structure. The idea of hidden tags is to make tags also useful for workflow and structure use cases:

Example 1: I want to tag a post with needs-review once I’ve finished writing it so my editor can pick it up. At the moment you can do this, but you have to remember to remove the tag before publishing, and there is also not a good way to view all the posts marked with need-review in the admin panel.

Example 2: I want to implement link-posts which just link out to another site using a tag to mark my link posts so that my theme can handle them differently. I can tag all these posts as link and handle this in my theme, however I also get link output in the tags list and all of these posts appear on /tag/link/ which isn’t ideal.

Implementation

To solve this, tags being set to ‘hashtag’ will have two major impacts:

  1. There will not be a page at /tag/:slug/ for this tag
  2. This tag will not be output by the {{tags}} helper

The tag will still be returned by the API like any other tag, and available to theme, meaning it will still be possible to use {{#has tag="#hashtagname"}} to check if the tag is set on a post.

One minor potential confusion point will be that any theme which has opted to cycle through tags manually rather than use the {{tags}} helper will show hidden tags. These themes will need updating with a {{^unless hashtag}} condition inside their tag loops.

Creating hashtags

When adding tags in the editor, there’s only a way to specify the name, rather than the type of tag. To combat this and make adding hidden tags quick & easy, it would be great if this could be controlled using a simple prefix. E.g. #needs-review. Any tag that has a # at the start of the name should automatically be marked as a hashtag. To resolve naming clashes in slugs between hidden and non-hidden tags with similar names, I think it would make sense to prefix the slugs for any hidden tags auto-created with a # with hash-``. So if I already havelinktag, and I create a#linktag, the slug for the first would belinkand for the secondhash-link`, etc.

Filtering in the admin UI

To really complete the power of this new feature, we need to be able to filter posts by tags in the admin UI. There are two aspects to this which I can think of:

  1. Showing posts which match by tag as well as title in the autocomplete search box
  2. Being able to get from a tag to a filtered content screen list of the posts that match that tag

I think there are a couple of potential investigations / spikes to do here around what can be done with the autocomplete search & content screen - can we list posts by tag in the autocomplete results? Can we make it so that pressing ‘enter’ on a term rather than clicking an item in the dropdown results in a filtered content screen list? How does it feel to have this result in a filter rather than a direct go-to-resource action as it does now?

Tasks

Prep:

  • Add labs flag for internal tags
  • Rework the server-side labs utility to be synchronous (so that {{tags}} doesn’t become async)
  • Bonus: get config override working for client-side labs again
  • Update DB to have visibility property

When the labs flag is checked:

  • Add new checkbox to tag management screen to mark/unmark a tag as hashtag
  • Filter the result from {{tags}} to not include hashtags
  • Return a 404 from /tags/:slug/ for hashtags
  • Create tags starting with # as a hashtag in the tag input component
  • Display hashtags in the content list

Other:

  • Spike on the autocomplete & content list filter to see what works easily and if there are any dependencies or other requirements here.

Cleanup:

  • Remove labs flag
  • Add proper tests for 404 tag, and tags.read() with hash parameter

Issue Analytics

  • State:closed
  • Created 8 years ago
  • Comments:6 (4 by maintainers)

github_iconTop GitHub Comments

1reaction
ErisDScommented, Sep 28, 2016

@WaqasIbrahim Tag names have never been suitable for use as class names, as they can include any character except , that includes spaces, tabs, etc. Instead, you should use the slug version of the name for a classname. The sluggified name is all lowercase and hyphenated and therefore suitable for class names.

1reaction
ErisDScommented, Jun 10, 2016

Since the original issue for this feature was written, we’ve done most of the implementation. However, the spec has changed a little bit.

Originally, we were referring to these tags as “hidden tags” because they are hidden from the blog & the boolean field used to mark them in the DB was called hidden. Then they became “hashtags” because they are prefixed with # and look like social media style #hashtags , however over time that name for the feature has evolved into the slightly clearer “internal tags”.

We are no longer using a simple boolean field in the database to mark these tags as “hidden”, but instead we now have a generic field called visibility which is a string and appears on tags, posts and users. It has validation at the model layer which restricts the value so that it operates as an enum. Across the board the default value is public, but tags also support a value of internal which is used to indicate an internal tag.

From an API perspective, this gives us lots of flexibility for adding various levels of visibility to the main models. However, from a theming perspective, it means that it’s no longer easy to check the boolean flag of whether a particular tag is an internal tag or not. So, this part of the spec is no longer valid:

One minor potential confusion point will be that any theme which has opted to cycle through tags manually rather than use the {{tags}} helper will show hidden tags. These themes will need updating with a {{^unless hashtag}} condition inside their tag loops.

Handlebars doesn’t let us compare strings, so within a foreach loop, it’s now not possible to filter out the internal tags - you have to use {{tags}}. This brought me to a new, and I think better idea.

With the new global concept of visibility on all of our core resources, it makes sense to honour this property in the {{foreach}} helper. We made a decision back at the beginning of the theme API to design our own loop helper rather than use the built-in handlebars one… so let’s make use of that to correctly reflect the business logic of a Ghost theme.

The {{#foreach}} helper & {{tags}} helper will both be updated to, by default, only output items which have a visibility of public. They would also both have a new visibility attribute added to them, that allows a developer to override the default behaviour.

By default {{#foreach "tags"}} would behave the same as {{#foreach "tags" visibility="public"}} By default {{tags}} would behave the same as {{tags visibility="public"}}

If you wanted to override the behaviour and output all tags, the helpers could be overridden with {{#foreach "tags" visibility="public, internal"}} or {{tags visibility="public, internal"}}. We could also consider supporting a value of all.

Read more comments on GitHub >

github_iconTop Results From Across the Web

The Best Ways to Organize Your Files with Tags and Labels
If you want to take your tagging to the next level, create a workflow that sends information you tag in one app to...
Read more >
Placement tags - Campaign Manager 360 Help
Learn how Campaign Manager 360 tags work and what types of placement tags you can download. Expand all sections.
Read more >
Organizing Your Work Through Tags - Notejoy
Tags can be a powerful tool to add an additional lens to organize the work, especially when you're working with complex projects. Rigid...
Read more >
Edit document structure with the Content and Tags panels ...
Follow these steps in Adobe Acrobat Pro to view and edit tags, add alternate text to tags, create a new child tag, and...
Read more >
How to build a tagging structure - Guru's Help Center
Once you have your list of tags specific to a department or Collection, organize this list into different topics, groups, etc. similar to...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found