The bmannconsulting.com website

bluesky

+16 -2
_includes/head.html
···
{% if page.frame %}
<!-- Open Frames Custom -->
<meta property="fc:frame" content="vNext">
{% if page.frame.button1 %}
<meta property="fc:frame:button:1" content="{{ page.frame.button1.label }}">
<meta property="fc:frame:button:1:action" content="{{ page.frame.button1.action }}">
<meta property="fc:frame:button:1:target" content="{{ page.frame.button1.target }}">
{% endif %}
{% else %}
<!-- Open Frames Default -->
<meta property="fc:frame" content="vNext">
<meta property="fc:frame:button:1" content="🌱 Home">
<meta property="fc:frame:button:1:action" content="link">
<meta property="fc:frame:button:1:target" content="https://bmannconsulting.com">
-
<meta property="fc:frame:button:2" content="🦋 Bluesky">
<meta property="fc:frame:button:2:action" content="link">
-
<meta property="fc:frame:button:2:target" content="https://bsky.bmann.ca">
<meta property="fc:frame:button:3" content="💬 Drips">
<meta property="fc:frame:button:3:action" content="link">
<meta property="fc:frame:button:3:target" content="https://www.drips.network/app/bmann.eth">
···
{% if page.frame %}
<!-- Open Frames Custom -->
<meta property="fc:frame" content="vNext">
+
{% if page.frame.image %}
+
<meta property="fc:frame:image" content="{{ page.frame.image }}">
+
<meta property="fc:frame:image:aspect_ratio" content="{{ page.frame.image-aspect-ratio }}">
+
{% endif %}
{% if page.frame.button1 %}
<meta property="fc:frame:button:1" content="{{ page.frame.button1.label }}">
<meta property="fc:frame:button:1:action" content="{{ page.frame.button1.action }}">
<meta property="fc:frame:button:1:target" content="{{ page.frame.button1.target }}">
{% endif %}
+
{% if page.frame.button2 %}
+
<meta property="fc:frame:button:2" content="{{ page.frame.button2.label }}">
+
<meta property="fc:frame:button:2:action" content="{{ page.frame.button2.action }}">
+
<meta property="fc:frame:button:2:target" content="{{ page.frame.button2.target }}">
+
{% endif %}
+
{% if page.frame.button3 %}
+
<meta property="fc:frame:button:3" content="{{ page.frame.button3.label }}">
+
<meta property="fc:frame:button:3:action" content="{{ page.frame.button3.action }}">
+
<meta property="fc:frame:button:3:target" content="{{ page.frame.button3.target }}">
+
{% endif %}
{% else %}
<!-- Open Frames Default -->
<meta property="fc:frame" content="vNext">
<meta property="fc:frame:button:1" content="🌱 Home">
<meta property="fc:frame:button:1:action" content="link">
<meta property="fc:frame:button:1:target" content="https://bmannconsulting.com">
+
<meta property="fc:frame:button:2" content="🔖 Tagged{% for tag in page.tags %} #{{ tag }}{% endfor %}">
<meta property="fc:frame:button:2:action" content="link">
+
<meta property="fc:frame:button:2:target" content="https://bmannconsulting.com/notes/">
<meta property="fc:frame:button:3" content="💬 Drips">
<meta property="fc:frame:button:3:action" content="link">
<meta property="fc:frame:button:3:target" content="https://www.drips.network/app/bmann.eth">
+19 -3
_journals/2024-04-21_1024.md
···
---
-
title: "April 21st, 2024"
-
date: "2024-04-21, 10:24:06 -07:00"
section: journal
-
aliases: []
---
Going through some open tabs and made a bunch of updates. Now took myself to the coffee shop to work on some blog coding.
···
There aren't that many entries on here because I have more in the old Logseq notes with [github](https://notes.bmannconsulting.com/#/page/github) and [git](https://notes.bmannconsulting.com/#/page/git) properties.
And separately, I'd like to capture my [1.4K starred repos on Github](https://github.com/bmann?tab=stars). The "signal" of me adding a notes page is stronger than "merely" starring on Github, but it should at least contribute to a personal search index (which again leads into [[Community Search Engines]] too).
···
---
+
title: April 21st, 2024
+
date: 2024-04-21, 10:24:06 -07:00
section: journal
+
excerpt: A log of some blog coding that I did, including more Frames support, canonical links, article and code filtered listing pages, and this excerpt field.
---
Going through some open tabs and made a bunch of updates. Now took myself to the coffee shop to work on some blog coding.
···
There aren't that many entries on here because I have more in the old Logseq notes with [github](https://notes.bmannconsulting.com/#/page/github) and [git](https://notes.bmannconsulting.com/#/page/git) properties.
And separately, I'd like to capture my [1.4K starred repos on Github](https://github.com/bmann?tab=stars). The "signal" of me adding a notes page is stronger than "merely" starring on Github, but it should at least contribute to a personal search index (which again leads into [[Community Search Engines]] too).
+
+
**Excerpt for Journals**
+
+
This is a very long journal post! My RSS automated cross posting with [[Fedica]] would attempt to turn this into a very very long set of threaded posts.
+
+
I'll add an excerpt field which will get used in the RSS feed if it excepts.
+
+
```liquid
+
{% raw %}
+
{% if post.excerpt %}
+
{% assign description = post.excerpt %}
+
{% else %}
+
{% assign description = post.content %}
+
{% endif %}
+
{% endraw %}
+
```
+12
_journals/2024-04-21_1252.md
···
···
+
---
+
title: April 21st, 2024
+
date: 2024-04-21, 12:52:09 -07:00
+
section: journal
+
link: https://bmannconsulting.com/notes/bluesky-custom-feeds-for-premium-content/
+
tags:
+
- Ghost
+
- ATProtocol
+
---
+
I added a few notes to [[Feedback on Federating Ghost]] on how this could be done using [[ATProtocol]].
+
+
One idea I think is novel that I wrote up in more detail: [[Bluesky Custom Feeds for Premium Content]]
+2
_layouts/note.html
···
<h1 style="text-transform:capitalize;">{{ page.title }}</h1>
{% if page.link %}
<strong><a href="{{ page.link }}">{{ page.link | remove: "https://" | truncate: 42 }}</a></strong>{% if page.author %}, by {{ page.author }}{% endif %}{% if page.published %}, {{ page.published | date: "%B %-d, %Y" }}{% endif %}<br />
{% endif %}
{% unless page.published %}
···
<h1 style="text-transform:capitalize;">{{ page.title }}</h1>
{% if page.link %}
<strong><a href="{{ page.link }}">{{ page.link | remove: "https://" | truncate: 42 }}</a></strong>{% if page.author %}, by {{ page.author }}{% endif %}{% if page.published %}, {{ page.published | date: "%B %-d, %Y" }}{% endif %}<br />
+
{% elsif page.wikipedia %}
+
<strong>wikipedia:</strong>&nbsp;<a href="{{ page.wikipedia }}">{{ page.wikipedia | remove: "https://" | truncate: 42 }}</a><br />
{% endif %}
{% unless page.published %}
+26
_notes/Bluesky Custom Feeds for Premium Content.md
···
···
+
---
+
tags:
+
- ATProtocol
+
- premiumcontent
+
---
+
[[Bluesky]] already has built in support for [[Bluesky#Custom Feeds|custom feeds]]. Could this be used to create premium content feeds?
+
+
This could look like subscribers-only content, but available and readable directly within Bluesky or any [[ATProtocol]] that supports custom feeds.
+
+
This is most relevant for a kind of ATProtocol-based "subscribe to my blog or newsletter" integration -- [[Substack]] or [[Ghost]] being two common paid subscriber platforms.
+
+
I'll use Ghost as my example.
+
+
- The "My Cool Ghost Site" has both free and paid memberships; some content is available to all members -- sent via email, in RSS, and posted to the blog
+
- Paid members get access to premium content -- they get it sent via email and/or can login to the Ghost blog to read it
+
- assuming Ghost / a custom plugin has a feature to link your Ghost membership with your Bluesky login
+
- The plugin would also generate endpoints for a Bluesky compatible custom feed
+
- The algorithm is pretty simple here -- if the currently logged in user is a paid member, show them free and premium content; else, only show free content
+
+
Right now all content is public on Bluesky, so you could still fetch the content / navigate to it. In fact, can you generate posts in a custom feed??? Or does it first have to be posted to an account, so that it could be included?
+
+
Maybe something with blocks? Have a free Bluesky account, `@my-cool-ghost-site.com`, and a premium one, `@members.my-cool-ghost-site.com`. When someone adds the custom feed, if they aren't a paid member, block them.
+
+
Blocking everyone on Bluesky (pre-emptively!) except for subscribers is not really a great method. This is probably another area where a Lexicon that supports premium content could be used.
+
+
And, this might just be way easier to implement by adding [[Open Frames for Bluesky]].
+11 -2
_notes/Bluesky.md
···
- ATProtocol
link: https://blueskyweb.xyz
---
-
Website: <https://blueskyweb.xyz>
> We‘re building the [AT Protocol](https://atproto.com/), a new foundation for public conversation and social networking which gives creators independence from platforms, developers the freedom to build, and users a choice in their experience.
The company is a Public Benefit Corporation that created the [[ATProtocol]] and built and runs the [Bluesky microblogging platform](https://baky.app).
-
[[Tim Bray]] collected [Facts and opinions about Bluesky](https://www.tbray.org/ongoing/When/202x/2023/04/28/Bluesky) because so many people were hating on it, mostly with misinformation.
···
- ATProtocol
link: https://blueskyweb.xyz
---
> We‘re building the [AT Protocol](https://atproto.com/), a new foundation for public conversation and social networking which gives creators independence from platforms, developers the freedom to build, and users a choice in their experience.
The company is a Public Benefit Corporation that created the [[ATProtocol]] and built and runs the [Bluesky microblogging platform](https://baky.app).
+
[[Tim Bray]] collected [Facts and opinions about Bluesky](https://www.tbray.org/ongoing/When/202x/2023/04/28/Bluesky) because so many people were hating on it, mostly with misinformation.
+
+
## Custom Feeds
+
+
From the [docs](https://docs.bsky.app/docs/starter-templates/custom-feeds):
+
+
> Custom feeds, or feed generators, are services that provide custom algorithms to users through the AT Protocol. This allows users to choose their own timelines, whether it's an algorithmic For You page or a feed of entirely cat photos.
+
>
+
> This is a starter kit for creating feed generators on atproto. It's not feature complete, but should give you a good starting ground off of which to build and deploy a feed.
+
>
+
> You can skip this tutorial and clone the TypeScript starter template directly [here](https://github.com/bluesky-social/feed-generator), or use community templates in [Python](https://github.com/MarshalX/bluesky-feed-generator) or [Ruby](https://github.com/mackuba/bluesky-feeds-rb).
+14 -2
_notes/Feedback on Federating Ghost.md
···
---
image: /assets/2024/ghost_logo_black.jpg
---
A [survey](https://tally.so/r/m67X4P) asking for feedback on Federating [[Ghost]]
···
I would interact with more Ghost sites in the "comments" if I didn't have to create new accounts all the time!
I already recommend [[Ghost]] and could now consider using it for use cases that look more like community servers use cases.
-
---
-
I linked to [[2024-04-21_0804|Matthew Bogart's write up answering this survey]].
···
---
image: /assets/2024/ghost_logo_black.jpg
+
tags:
+
- Ghost
+
- ActivityPub
---
A [survey](https://tally.so/r/m67X4P) asking for feedback on Federating [[Ghost]]
···
I would interact with more Ghost sites in the "comments" if I didn't have to create new accounts all the time!
I already recommend [[Ghost]] and could now consider using it for use cases that look more like community servers use cases.
+
# Updates
+
+
I linked to [[2024-04-21_0804|Matthew Bogart's write up answering this survey]].
+
+
## Ghost + Bluesky's ATProtocol
+
+
I guess John O'Nolan has a cross poster, since he [posted the same thing to Bluesky](https://bsky.app/profile/bmann.ca/post/3kqlzleitr223). Would my answer be different for [[ATProtocol]]?
+
I'd like to see [[Bluesky]] support a blog Lexicon with full posts.
+
Login linking would be similar.
+
+
Could you make a custom feed for premium content??? I think so, and I think it's worth a write up: [[Bluesky Custom Feeds for Premium Content]]
+5
_notes/Open Frames for Bluesky.md
···
···
+
Supporting [[Open Frames]] in Bluesky
+
+
## Proof of Concept
+
+
Pick an existing open source web client and add in rendering support for Open Frames.
+14
_notes/Substack.md
···
···
+
---
+
wikipedia: https://en.wikipedia.org/wiki/Substack
+
tags:
+
- organization
+
- platform
+
- newsletter
+
---
+
> Substack is an American online platform that provides publishing, payment, analytics, and design infrastructure to support subscription newsletters. It allows writers to send digital newsletters directly to subscribers. Founded in 2017, Substack is headquartered in San Francisco.
+
+
## Alternatives
+
+
If you must use Substack, at least map a domain to it.
+
+
But really, just don't use it. Use [[Ghost]] as the most direct replacement.
+6 -1
fedica-hashtags.xml
···
<dc:creator>Boris Mann</dc:creator>
{% comment %} Capture: we loop through all of the tags and make a list of hashtags separated by spaces {% endcomment %}
{% capture taglist %}{% for tag in post.tags %} #{{ tag }}{% endfor %}{% endcapture %}
-
{% assign description = post.content | append: taglist %}
<description>{{ description | xml_escape | replace: 'src=&quot;/', 'src=&quot;https://bmannconsulting.com/' | replace: 'href=&quot;/', 'href=&quot;https://bmannconsulting.com/' }}</description>
{% if post.link %}
<link>{{ post.link | xml_escape }}</link>
···
<dc:creator>Boris Mann</dc:creator>
{% comment %} Capture: we loop through all of the tags and make a list of hashtags separated by spaces {% endcomment %}
{% capture taglist %}{% for tag in post.tags %} #{{ tag }}{% endfor %}{% endcapture %}
+
{% if post.excerpt %}
+
{% assign description = post.excerpt %}
+
{% else %}
+
{% assign description = post.content %}
+
{% endif %}
+
{% assign description = description | append: taglist %}
<description>{{ description | xml_escape | replace: 'src=&quot;/', 'src=&quot;https://bmannconsulting.com/' | replace: 'href=&quot;/', 'href=&quot;https://bmannconsulting.com/' }}</description>
{% if post.link %}
<link>{{ post.link | xml_escape }}</link>
+6 -1
journal.xml
···
{% for post in sortedblog limit:20 %}
<item>
<dc:creator>{{ site.name | xml_escape }}</dc:creator>
-
<description>{{ post.content | xml_escape | replace: 'src=&quot;/', 'src=&quot;https://bmannconsulting.com/' | replace: 'href=&quot;/', 'href=&quot;https://bmannconsulting.com/' }}</description>
{% if post.link %}
<link>{{ post.link | xml_escape }}</link>
{% else %}
···
{% for post in sortedblog limit:20 %}
<item>
<dc:creator>{{ site.name | xml_escape }}</dc:creator>
+
{% if post.excerpt %}
+
{% assign description = post.excerpt %}
+
{% else %}
+
{% assign description = post.content %}
+
{% endif %}
+
<description>{{ description | xml_escape | replace: 'src=&quot;/', 'src=&quot;https://bmannconsulting.com/' | replace: 'href=&quot;/', 'href=&quot;https://bmannconsulting.com/' }}</description>
{% if post.link %}
<link>{{ post.link | xml_escape }}</link>
{% else %}