From e88b2bd17a2862b7244cb9d39e386c37ddda7f4a Mon Sep 17 00:00:00 2001 From: garrettmills Date: Thu, 9 Jan 2025 10:45:20 -0500 Subject: [PATCH] Add Fun With Bookmarks post --- .../blog-posts/Fun-With-Bookmarks.md | 76 +++++++++++++++++++ src/app/services/MarkMark.service.ts | 2 +- 2 files changed, 77 insertions(+), 1 deletion(-) create mode 100644 src/app/resources/blog-posts/Fun-With-Bookmarks.md diff --git a/src/app/resources/blog-posts/Fun-With-Bookmarks.md b/src/app/resources/blog-posts/Fun-With-Bookmarks.md new file mode 100644 index 0000000..7bcad35 --- /dev/null +++ b/src/app/resources/blog-posts/Fun-With-Bookmarks.md @@ -0,0 +1,76 @@ +--- +title: Fun With Bookmarks +slug: Fun-With-Bookmarks +date: 2025-01-09 07:30:00 +tags: +- meta +- markmark +--- + +A while back, I started experimenting with a way of storing my bookmarks (read: my random text document full of untitled links) as a Markdown document, which I affectionately dubbed "[MarkMark](https://garrettmills.dev/markmark)" — a standard format for links, descriptive text, tags, and dates. Here's a sample from [my bookmarks](https://garrettmills.dev/links): + +```markdown +# Cycling + +- Spencer McCullough's bike trip to 48 national parks (+ an excellent bike camping map) + - https://onelongtrip.bike/ + - https://gobikecamping.com/map +- Helmet Wind Straps + - https://youtube.com/shorts/8-Ph6CjKopY?si=QGVb7HrKT7FejGZI +- A love letter to bicycle maintenance and repair + - https://tegowerk.eu/posts/bicycle-repair/ +``` + +I published MarkMark v1.0 back in November 2023 (!!), but I never fully started using it for two reasons: + + +1. I wanted to be able to organize and syndicate links by date, and +2. more importantly, adding a link meant committing a change to my [website code](https://code.garrettmills.dev/garrettmills/www/src/commit/c852fbd628bfd7903ef9814becfb8d8e77dfcb40/src/app/resources/markmark/links.mark.md) and fully re-deploying it every time. + +Since I've been feeling the urge to tinker, I've made some changes to help with both. + + +## v1.1: It's all about that date + +I love RSS and the indie-web ([see here](https://garrettmills.dev/blog/feeds)) and one of the main ways I discover new parts of it is thanks to fantastic link blogs like [Jason Kottke](https://kottke.org/) and [LinkMachineGo](https://www.timemachinego.com/linkmachinego/). + +While I'm not running a link blog, and I have no delusions of readership, I like the idea of being able to syndicate my bookmarks via RSS. + +This would work if my MarkMark document was organized by date, but, since it's not, an [update to the spec](https://xkcd.com/927/) was required. MarkMark v1.1 introduces a date notation for links: + +```markdown +- A fantastic link title goes here (2025-01-09) + - https://example.com/home +``` + +The dates are optional, but give me a way to track when links were added to my bookmarks, which means I can now generate an [RSS feed](https://code.garrettmills.dev/garrettmills/www/src/commit/c852fbd628bfd7903ef9814becfb8d8e77dfcb40/src/app/services/blog/MarkMarkBlog.service.ts#L28). + +My current implementation publishes feed entries for each link in my bookmarks that has a date, along with the title of its section, description, and URL(s). + +![](https://static.garrettmills.dev/assets/blog-images/fun-with-mm-1.png) +
You can find these feeds in RSS, Atom, and JSON format on the links page.
+ + +## Reading links from Outline + +The deployment process for my website isn't *difficult*, but it does require a [Docker build](https://code.garrettmills.dev/garrettmills/www/src/branch/master/package.json#L44), which turns out to be too much work every time I just want to save a link. + +As I mentioned in my [Default Apps 2024](https://garrettmills.dev/blog/2025/01/07/Default-Apps-2024/) post, my knowledge base of choice is the self-hosted version of [Outline](https://www.getoutline.com/), which I have found to be quite good. One of the things I like about Outline is that it stores document contents as Markdown internally and has a well-documented REST API (you can probably see where this is going). + + ![](https://static.garrettmills.dev/assets/blog-images/fun-with-mm-2.png) + +The `/links` page now, with some caching, reads my MarkMark document directly from my Outline instance rather than a hard-coded file. Since MarkMark is just a subset of the [CommonMark](https://commonmark.org/) syntax, I can make use of Outline's markdown formatting for headers, lists, links, and code: + +![](https://static.garrettmills.dev/assets/blog-images/fun-with-mm-3.png) +
I did have to add some special logic to undo the escaping Outline adds to the MarkMark preamble (the lines starting with [//]:).
+ +This is *way* easier to add to/organize day-to-day, and the updates get pulled into my website and RSS feeds automatically. + + +## Future Work + +I want to build a Firefox extension for saving links to my MarkMark document in Outline — something where I can click the button on a webpage and pre-fill the title, description, and today's date. It'll have to use the Outline API to load the list of categories and tags, then my [MarkMark parser collection](https://code.garrettmills.dev/garrettmills/www/src/branch/master/src/markmark) to add the link and update the Outline document automatically. + +More generally, I like this idea of building semi-dynamic integrations using Outline. I already use it to draft all my blog posts before publishing. It reminds me a lot of the [halcyon days of the old web](https://en.wikipedia.org/wiki/Microsoft_FrontPage). I wonder if there are any other uses. + +One of my themes for 2025 is to work smaller — build smaller projects, write smaller (more frequent) posts, read smaller sources, &c. The MarkMark spec and its small collection of tools feels like a good way to start. diff --git a/src/app/services/MarkMark.service.ts b/src/app/services/MarkMark.service.ts index 4ae16f4..9a762cf 100644 --- a/src/app/services/MarkMark.service.ts +++ b/src/app/services/MarkMark.service.ts @@ -24,7 +24,7 @@ export class MarkMarkService { let content = await this.cache.fetch('www-markmark-content') if ( !content || this.config.get('server.debug') ) { content = await this.readFromOutline() - const expDateEpoch = (new Date).getTime() + (15 * 60 * 1000) + const expDateEpoch = (new Date).getTime() + (60 * 60 * 1000) // cache for 1hr await this.cache.put('www-markmark-content', content, new Date(expDateEpoch)) }