Digital Garden Spec
Posted in December 2024
Epistemic status: I haven't thought through the practicality or security implications of this. I'm just tossing an idea out there with the hope that someone can build on it. It's not very tidy writing.
summary
there’s an idea called the digital garden, which is to lay out stuff on personal websites based around context and non-linear links. think a wiki rather than an rss/algorithmic feed. however, because these are nonstandard, if you want to keep track of them you can’t really just chuck them into an rss reader or something similar, because the whole point is that they can’t be represented as an algorithmic timeline. additionally, these don’t grant context in a human readable way.
so i figured i would design this spec as a thought experiment that i dont know if anyone would ever actually use. this isn’t rigid, but i wanted to lay something out that people could build if they wanted (either build a parser for or build on for a better spec). theres probably a lot of flaws here, but whatever. thought experiment! you probably shouldn’t use this spec for this reason. that being said, if you do, please include a tag somewhere that has data-dgarden-spec="aprilghost-v0-draft-do-not-use"
in it, so clients know you agree to specifically the things i talk about here. if you don’t, that’s ok, i’m just some weird girl. its not perfect. you can tell me about why it isnt perfect if you like.
please check the rest of the paragraphs before you do this, but the simplest way of using it: on your sitemap or whatever root page:
- add the class
dgarden-branch
to the element containing all the links - add the class
dgarden-plant-link
to anything that links to another page (plant) in your garden (and make sure any links you want to track within that page are in an element with thedgarden-plant
ordgarden-branch
class)
that’s all you need to do! a client that understands this can use that to figure out links between plants, and links from plants to external sites, so they can use it to let a follower know when new things are made and to show them info about what you talk about. you can also:
- make a new plant within the page by adding the class
dgarden-plant-inline
to the element that contains it (it must have an id) - add the
data-dgarden-kind="kind-of-link"
attribute to external links (or anything that refers to another work) within a plant to say what type of link they are; replacekind-of-link
with some of the examples below - add the
data-dgarden-uri="some-uri"
attribute to show that a link points to some other identifier(s), like an ISBN or a DOI. if you want to specify more than one, add angle brackets:data-dgarden-uri="<uri:1><uri:2><uri:3>"
- specify tags: include an element with
data-dgarden-tag="some-tag"
.
this format doesn’t say anything about the content of a web page or how it should be displayed. it’s just a an easy and opt-in way of indicating links between things, which also doubles as a way of keeping clients up to date. because of that, it can be used even if you don’t specifically lay your website out as a digital garden. indicating things like this on your site allows for additional building of context. it can allow clients that understand this spec to map out how things you talk about and relate to other things in the world.
my thought process is, i want to be able to do 3 things:
- know if people i follow publish new things (some people may not find RSS useful or helpful for them)
- make it easy to find links to something from the people i have chosen to pay attention to - think about finding what people have said on whatever movie, book, article, paper, website, anything else
- to see at a glance what those people have talked about and linked to in general - view what they’ve talked about or find valuable or interesting, or links to their friends/collaborators
think about the idea of a media thread on twitter. people post what they look at, and it allows people to share the things they like much more easily. with this you can share something like that easier, and other people can find it easier. something like that.
it being opt-in is important. so before i talk about how to make you site support it, let me clarify: when i say opt-in, i mean that by adding that spec attribute i mentioned above you opt in to being viewed by individual people who have specifically chosen to add your website. that person could have a client, like an RSS reader, that lets them add multiple sites and figure things out about the network they personally curate. however, this does not grant external services or scrapers consent to make huge databases of these attributes automatically, nor does it grant consent for clients to share this info between users. your network of digital gardens you follow exists for you, on your device or within your account in a hosting provider, and if there are more public databases you want to include it in then that a) should be decided by the website owner exclusively and b) is not within the scope of this.
rationale
when i say “client” below, i mean a program that parses this specification.
my main inspiration is microformats like h-entry. people already make digital gardens, people already lay their websites out in cool ways, and we should make it as easy as possible for them to support whatever specification exists, because otherwise they won’t do it. adding classes seems like the easiest way of going about it. you could also theoretically chuck all of this info into a separate XML file and point clients to there, if your site generator doesn’t support you adding extra classes to things easily.
i mentioned the opt-in nature before. im conscious of how this could, theoretically, have surveillance purposes. but my thought process is that websites are already comprised of links, and scrapers could already scrape all of this information and build a graph for anyone to look up without your consent anyway. this is a model that allows you to opt in explicitly to individuals building limited graphs within their own clients.
all this to say, if you use this for the purposes of conducting surveillance on vulnerable people and their relationships to people and things in the world im stealing something from your house!
additionally, the client should take me to the page where it’s hosted, so im not imposing any demands on how someone should interpret their work either. a client must not add related gardens without making the user explicitly do an action to consent to it. which is to say, you shouldn’t add a garden and then a billion others also get added because that garden linked to them once, and a .
i would be a hypocrite for talking about “digital gardens” while encouraging tech use that wastes energy and ruins the planet, so below are some thoughts on that before we get into the spec proper.
it makes sense to use this as a way of being notified of new pages. if you want to check for newly added nodes, only refresh the pages that point to other nodes (indicated with dgarden-branch
), and you shouldn’t do it more than once a day.
this is NOT intended to be a way of checking for updates on every single page. clients must not allow for easy refreshes that spam check the contents of each page instantly. this causes more cpu time used by both the client and the webserver, no matter how tiny. if you disregard this, at least spread the requests out to avoid DDoSing. you can also send a request with the HEAD
method to a page to see if it’s been updated, which will only return the HTTP header and not the body. this can contain a date, though some dynamic sites will always return newer dates each time, so be careful with it.
this talk of environmental impact means i also have to contend with how it relates to AI and blockchain technology.
on the first, bots can already scrape your website easily and figure out all of these links for themselves. this is an opt-in model: if something parses this spec, it needs your consent to scan your website like this, which you provide by using these tags and attributes that aren’t used in other ways. on the second, one of the tenets of a digital garden is that ideas grow and change, and sometimes bits get pruned. people learn and grow, and their ideas and opinions change, and the digital garden ethos talks about the “right to be wrong”. i dont want to create technology that encourages surveillance of vulnerable people. clients MUST (not should, MUST!) respect these things by not keeping/caching version histories, or keeping the graph of relations of previous versions. you can see how this is incompatible with a blockchain. a client must not make it easy for the user to manually download a specific version of a page: if they want to save it, they must do it thenself with the browser.
they must cache the pages to prevent constant strain on the webserver, of course. websites and pages sometimes go down as well. however, if a client fails to retrieve the info of a garden, you must let the user know that and how long ago the last success was.
examples and details
so here are some explanations of what each tag or property does, with some examples.
your garden is your site, and each page (or element of a page) within your site that you want to include is a plant. so basically a garden is kind of like a graph, in which a plant is a (type of) node. a branch is a type of plant that can define new plants.
let’s say your garden is at https://aprilghost.net/garden
. within that page, you include the element <div class="dgarden-branch">...</div>
. this makes this a plant; specifically a branch, which can declare new plants. to make it unable to declare new plants, use dgarden-plant
.
within a branch (and not a normal plant), you can declare new plants:
- at a link like
<a class="dgarden-plant-link" href="creative-process.html">My Creative Process</a>
. in this example, the new plant’s URL will behttps://aprilghost.net/garden/creative-process.html
and it’s title will be My Creative Process. the client will get info about this plant by loading the XML file at the URL, and parsing the children of elements matching.dgarden-plant
or.dgarden-branch
. if that link is not in the same domain, it’s an invalid plant and should be considered an external link instead. - within an element like
<div class="dgarden-plant-inline" id="creative-process">...</div>
. in this example, the new plant’s URL will behttps://aprilghost.net/garden#creative-process
. by adding a child element with thedgarden-title
class, you can give it text to make that the title of the plant. the client will get info about this plant by parsing the child elements of#creative-process
when you declare a new plant, it declares a directed link from that branch to that new plant within a client. any link to it from another plant (branch or not) will declare a link, unless that link has the dgarden-ignore
class. you can declare a plant multiple times, though it’s not necessary, and subsequent declarations may give it new titles.
you can also specify tags for plants. within the plant, you can add a data-dgarden-tag="some-tag"
attribute to any node. this link between a plant and a tag is bidirectional: a client should be able to view pages that are tagged with something on a per-garden basis, and should be able to see the tags on a plant. tags should not be assumed to mean the same thing between different gardens.
within a plant, you may declare links to other things, of course, because it’s the web. external links (href="https://..."
) within a plant (as in, the dgarden-plant
or dgarden-plant-inline
classes, not outside of those) must be automatically tracked by clients unless they have the dgarden-ignore
class. you can indicate what kind of link it is with the data-dgarden-kind
attribute. a client must parse this as free text, but i may as well specify some conventions here:
topic
- the topic of the workreferences
- a reference or citationrecommendation
- a recommendation of something else to check out that isn’t strictly related. could be considered “further reading”mirror
- somewhere else the work is hostedcredit-work
- credits some workcredit-entity
- credits some person or entity
you can have 0 or more of each of these in a plant. you can specify more details about the link with the data-dgarden-detail
attribute, which is also free text. you can specify additional URLs with data-dgarden-url="<url1><url2><url3>"
.
you can also specify URIs with data-dgarden-uri="<uri:1><url:2><url:3>"
. you don’t need to include angle brackets if there’s just one. a URI is some kind of identifier that doesn’t tell you how to resolve it. an ISBN is a good example: you can’t figure out what the book is from an ISBN nor where to get it or any other metadata but it still uniquely identifies the book. the URI also doesn’t have to be any specific format: a client should parse them and store them either way, and it may or may not know how to resolve it from there.
you can also include data-dgarden-kind
on a node with text without specifying any URLs or URIs at all! clients shouldn’t automatically assume any relation to any other links who share the same text though.
as an example, let’s say you made a video essay on youtube, and you have a page on your website talking about it. we could specify more info about it in a plant via these links:
<a href="https://youtube.com/..." data-dgarden-kind="mirror">here</a>
indicates where the youtube video is<a href="https://xyz.neocities.org" data-dgarden-kind="credit-entity" data-dgarden-detail="Additional Research">Jake</a>
credits Jake with “additional research” and links to their website<a href="..." data-dgarden-kind="credit-work" data-dgarden-detail="soundtrack" data-dgarden-uri="<iswc:xxxxxx><isrc:xxxxxx>"></a>
indicates that part of the soundtrack in that video is at that link, and also includes ISWC and ISRC codes that uniquely identifies the track and recording.<span data-dgarden-kind="topic">Kingdom Hearts 2</a>
indicates that the topic of the video is Kingdom Hearts 2, but doesn’t link to it.
finally, if we wanted to represent all of this in some data structure, ive laid out how it could be represented in YAML after checking the root and its plants, though this is not a requirement:
root-url: https://aprilghost.net/garden
plants:
- url: https://aprilghost.net/garden
plant-links:
- https://aprilghost.net/garden/creative-process.html
- https://aprilghost.net/garden#creative-process
- url: https://aprilghost.net/garden/creative-process.html
titles: [ My Creative Process ]
tags: [ some-tag ]
external-links:
- url: https://youtube.com/...
kind: mirror
text: here
- url: https://xyz.neocities.org
kind: credit-entity
detail: Additional Research
text: Jake
- url: ...
kind: credit-work
extra-uris:
- "isrc:xxxxxx"
- "iswc:xxxxxx"
- kind: topic
text: Kingdom Hearts 2
caching, indexing, storing in more efficient methods, displaying as a web, etc etc, is left as an exercise to the reader. but from this you could have an idea of how one might figure out who talks about what.
a lot of this could use user based/initiated annotation. for example, you could fetch the opengraph info on external links and cache that, or a user could annotate a website as belonging to a specific person.
additional things you can put on your root node to apply to other nodes within the same garden but also i haven’t thought through whether they are a good idea so maybe don’t do that:
alias
- indicates ways that some URIs or URLs map to each other within every node specified in this node. you may specify one wildcard as an asterisk, and whatever fits that wildcard for the “from” part replaces the asterisk in the “to” parts. you may also not add an asterisk, to say that one URI or URL is equivalent to one or more others. having more than one asterisk or having just an asterisk is disallowed. e.g.<whatever data-dgarden-from-uri="igdb:*"><whatever data-dgarden-to-uri="backlogged:*"/><whatever data-dgarden-to-url="https://igdb.com/*"/> </whatever>
. this means if you reference the URIigdb:my-game
it also automatically referencesbackloggd:my-game
andhttps://igdb.com/my-game
related
- indicates that one root node is part of the same garden as another root node. both nodes must say they are related to each other, otherwise the link is ignored.
in practice:
doi:*
andhttps://doi.org/*
should always map to each other