orchidhq / Orchid

Build and deploy beautiful documentation sites that grow with you
https://orchid.run
GNU General Public License v3.0
514 stars 53 forks source link

Atom and RSS feeds should add <link> elements to site header #310

Closed singularsyntax closed 4 years ago

singularsyntax commented 5 years ago

Syndication reader and management tools such as Feedbro do not find Orchid's automatically generated Atom/RSS feeds since <link> elements for them are missing from the site page's <head>.

I fixed this by adding the following hack to src/orchid/resources/templates/layouts/layoutBase.peb but a more complete solution should probably take into account if and how feed generation is enabled in config.yml:

<link rel="alternate" type="application/atom+xml" title="{{ site.about.siteName }} (Atom)" href="atom.xml"/>
<link rel="alternate" type="application/rss+xml" title="{{ site.about.siteName }} (RSS)" href="rss.xml"/>

Also, perhaps it would be useful to have a clickable icon on the page allowing visitors to add the feeds.

cjbrooks12 commented 5 years ago

I'm not very familiar with how feed readers find feeds. Do those links need to be on every page in the site, or just on the pages that are in a feed?

singularsyntax commented 5 years ago

The intent isn't to have an external feed reader crawl the site and build an Atom or RSS XML syndication of the content (though it's conceivable that could be done given sufficient metadata provided in each page and a fully-linked entry point), but just to point the reader at the site and retrieve an already built Atom or RSS file from the server (as Orchid already provides).

For example, Feedbro, a popular browser extension for feed reading, has a menu item "Find Feeds in Current Tab". Before including the above <link> elements, it doesn't find anything, but after including them it discovers the feeds and allows you to add them the collection of followed feeds the extension maintains.

I think it would make sense to include the <link> elements on a site's home page. It wouldn't hurt to include them on other pages as well, but it's not necessary.

cjbrooks12 commented 5 years ago

Do you have a couple examples of other sites that work correctly with Feedbro? I like the idea, but I would like to make sure to implement it in an "industry-standard" way. That is, not make a special case just for handling Feedbro or anything else, but actually finding out how it is generally expected to be set up across all sites.

singularsyntax commented 5 years ago

Yes - in fact GitHub itself syndicates recent commits as an Atom feed (look at the page source for this page):

<link href="https://github.com/JavaEden/Orchid/commits/dev.atom" rel="alternate" title="Recent Commits to Orchid:dev" type="application/atom+xml">

Unfortunately, there doesn't appear to be a more specific link relation type for site syndicates than alternate: IANA Link Relations

Also, have a look at: https://developer.mozilla.org/en-US/docs/Archive/RSS/Getting_Started/Syndicating#Adding_the_.3Clink.3E

singularsyntax commented 5 years ago

Other examples:

Probably many other well-known sites with article-oriented content provide feeds by this mechanism.

cjbrooks12 commented 5 years ago

Thank you for these links, they're very helpful!

Currently, there's not really a "good" mechanism for plugins to inject stuff other than styles/scripts into a page <head> tags. I'm gonna have to think through how to do this, it's gonna take a bit of work to get this working as you're expecting, unfortunately.

singularsyntax commented 5 years ago

There's no hurry, as just including <link> elements in the templates works just fine for now. It might be worthwhile to also think about how to generalize the solution to allow plugins to inject arbitrary elements (well, those that are allowed within <head>), since I can imagine additional use cases. For example, I've also added the following to my site's <head>:

<meta property="og:site_name" content="{{ site.about.siteName }}"/>
<meta property="og:url" content="{{ homepageUrl() }}"/>
<meta property="og:title" content="{{ site.about.siteName }} - {{ site.about.subtitle }}"/>
<meta property="og:description" content="{{ site.about.siteDescription }}"/>
<meta property="og:image" content="{{ site.about.avatar }}"/>
<meta property="og:type" content="website" />

These are the properties from Facebook's Open Graph protocol, which while not exactly a standard seems to be used by quite a few sites to generate a live URL preview/thumbnail when you paste a link into a textbox on the site (and Twitter has its own, similar <meta> tag properties which do the same thing).

Ideally, each type of page should be able to generate its own content for <head> according to the page context - for example, og:title for a site should resolve as above, but for a blog post should resolve to the blog post title. Likewise, og:image should resolve to the site avatar/logo at site scope, but the featured image for a blog post, etc.

cjbrooks12 commented 5 years ago

Yeah, a generalization of this would definitely be the goal. I've got a couple of ideas in mind, and neither one should be too terribly difficult, but I'd love to get your opinion on which one you think would be better.

1) "Meta components" - Basically the same thing as normal page components, but they render output to the <head> instead of the page body. They would be set up by plugins just the same as normal Components (so no new APIs), and are configured by end-users from Front Matter or config.yml in the same way as normal components. Pros: no need for new APIs, mentally the same thing as what you're already doing. Cons: not automatically applied, would need to be configured manually. 2) The alternative is to create a new API for plugins to register meta information automatically. There might be some minor configuration needed by end-users, but their usage would be closer to normal plugin configuration than setting up components. Pros: less for users to configure, richer site information without end-users needing to think about it. Cons: less flexibility in how it's applied, additional APIs mean more complexity for both users and plugin creators.

Personally, I think I'm leaning more towards option 1. More configuration for the end-users, but I think that's a good trade-off for overall lower complexity to both creating plugins and also building sites.

singularsyntax commented 4 years ago

I'm not sure if I can offer a useful opinion, given my limited understanding of Orchid's architecture and the plugin API.

But in general, I would aim for whatever solution offers the most seamless, "plug-and-play" experience for end-users as possible. I would also lean towards placing the larger burden on plugin developers, as 1) they have more expertise and are more capable of dealing with technical concerns, including configuration, and 2) the frequency of plugin creation is generally going to be much smaller than the frequency of application use, which should minimize work across the board (i.e. as a developer, you should have less on-going support effort for plugin developers than end-users if the software is optimized for the latter).

Taking the first use case - adding <link> elements to page headers for Atom/RSS feeds - this functionality currently resides in the Orchid Posts plugin, correct? But in some senses, it's a cross-cutting concern, since the task of producing an Atom or RSS feed might also be wanted for other kinds of content at some point, and also because a feed is an aggregating or many-to-one sort of process. So I wonder if "injecting" into a page <head> (i.e. a "push") is the right analogy, and if instead a "pull" or gathering process is a better way to think about it - and that might also affect resulting solution and APIs.

Also - does the current design allow for the Atom/RSS syndication process (which belongs to Posts) to get a whack at a site's home page (where I think you'd definitely want the syndication <link>s, since they're aggregating/global per above), or is only Post's own content in scope (where you might not want them, or the content might have some kind of sub-content (e.g. comments) that a more specific kind of feed scoped to the content type should be offered, or perhaps they should be configurable) ?

cjbrooks12 commented 4 years ago

A new meta-component has been added for this in 0.19.0

https://orchid.run/plugins/orchidposts#rss-and-atom-feeds